Bonjour
Le titre n'est pas très explicite mais je vais expliquer mon souci le mieux possible.
Dans une application, j'ai un composant qui affiche plusieurs blocs de données ( ici des repas pour exemple ) et chaque bloc de repas peut être déplacé avec un drag and drop.
J'ai essayé de faire le plus simple possible avec le moins de code, n'hésitez pas à me dire s'il y a une meilleurs façon de faire ( surtout que ça peut impacter la suite ).
Je sais déjà que lorsqu'il y a des aliments dans le repas, le "glissé" est moins sympas...
Voici donc ce composant:
Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 import React, { useState } from "react"; import FoodList from "./FoodList"; import "../../css/mealComposition.css" const Home: React.FC = () => { interface Meal { name: string, foods: Array<string> nbInputs: number } const [mealList, setMealList] = useState<Meal[]>([ {name: "Repas 1", foods: ["banane", "tomate"]}, {name: "Repas 2", foods: []}, {name: "Repas 3", foods: ["pain", "viande"]}, ]) const handleDragStart = (e: React.DragEvent<HTMLDivElement>) => { const targetElement = e.target as HTMLDivElement setTimeout(() => targetElement.classList.add('dragging'), 0) } const handleDragEnter = (e: React.DragEvent<HTMLDivElement>) => { const targetElement = e.target as HTMLDivElement const zone = document.querySelector('.mealDayContent') const draggedElement = document.querySelector('.dragging') const enterElementPositionY = targetElement.getBoundingClientRect().top const draggedElementPositionY = draggedElement.getBoundingClientRect().top zone.addEventListener('dragover', (e) => { e.preventDefault() }) if (enterElementPositionY > draggedElementPositionY) { zone.insertBefore(draggedElement, targetElement.nextSibling) } else { zone.insertBefore(draggedElement, targetElement) } } const handleDragEnd = (e: React.DragEvent<HTMLDivElement>) => { const targetElement = e.target as HTMLDivElement targetElement.classList.remove('dragging') } const addMeal = () => { const newMeal = {name: `repas ${mealList.length + 1}`, foods: [], nbInputs: 0} const updateMealList = [...mealList, newMeal] setMealList(updateMealList) } return( <> <div className="mealDay"> Repas de la journée: <button onClick={addMeal}> + </button> </div> <div className="mealDayContent"> {mealList.map((meal: Meal, index: number) => ( <div key={index} className="meal" draggable="true" onDragStart={(e) => handleDragStart(e)} onDragEnter={(e) => handleDragEnter(e)} onDragEnd={(e) => handleDragEnd(e)}> <div className="mealName"> {meal.name} </div> <FoodList foodList={meal.foods}/> </div> ))} </div> </>) } export default Home
Pour l'instant, je fais simple car j'apprends le drag and drop ( jamais fait avant encore moins avec React... !)
Il reste bien sûr à réorganiser l'objet mealList ( je me débrouillerai avec les index au moment du dragend )
Le problème, le vrai, est le suivant: mon composant Foodlist affiche une liste d'ingrédients et je voudrais pouvoir déplacer ces ingrédients
à l'intérieur d'un repas dans la foodList, mais aussi vers une foodList d'un autre repas.
Par exemple: je dois pouvoir glisser tomate dans le repas 3 ( n'importe ou dans la liste, avant le pain, après la viande ou entre les deux )
voici donc mon composant FoodList:
Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import React from "react"; interface FoodListProps { foodList: Array<string> } const FoodList: React.FC<FoodListProps> = ({foodList}: FoodListProps) => { return ( <div className="foodList"> {foodList.map((food: string, index: number) => ( <div key={index} draggable="true" className="food"> {food} </div> ))} </div> ) } export default FoodList
Quelles seraient les pistes ? Parce que pour le moment, le composant parent a un impact sur ce composant: ça déplace les aliments en dehors des repas !
( ce qui est tout à fait normal, vu que je n'ai rien codé! )
Je pourrais m'en sortir si j'avais tout dans un composant parent ( mapping des aliments ), mais je voudrais justement savoir comment faire dans ce cas.
De plus React, par principe, ça sert à faire des composants. Donc tout faire dans le même composant n'est pas correct.
J'ai mis un peu de CSS (pas la priorité pour l'instant):
Code css : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 input { display: block; margin-bottom: 10px; } .meal { border: 2px solid red; border-radius: 4px; margin: 10px; padding: 10px; cursor: move; } .mealName { margin-bottom: 10px; font-size: 25px; } .dragging { visibility: hidden; } .food { border: 1px solid black; border-radius: 4px; padding: 5px; margin-bottom: 4px; } .foodList { display: flex; justify-content: start; align-items: start; flex-direction: column; }
Évidemment, une piste sans librairie, parce que je veux apprendre...
Merci d'avance.
Laurent.
Partager