Exemple d’un composant gérant une liste de tâches à faire

Cet exemple présente un composant gérant une liste de tâches à faire en utilisant la fonction map() de Room.

Description du composant

Le composant présente un champ pour saisir le nom d’une tâche à ajouter et la liste des tâches déjà présentes. Une tâche de la liste comporte une case à cocher pour indiquer si la tâche est terminée ou pas, un champ pour modifier le texte de la tâche et un bouton pour la supprimer de la liste.

Le composant est une fonction nommée TodoList attendant une propriété todos et retournant un élément <div>.

La propriété todos est requise et doit être une donnée observable créée avec la fonction createData() de Room à partir d’un tableau à minima vide ([]). Les éléments du tableau sont des objets et un objet doit être constitué d’une propriété text contenant le nom de la tâche à faire (une chaîne de caractères) et d’une propriété done (un booléen) indiquant l’état de la tâche (terminée ou pas).

Un exemple de tableau :

const todos = [
{text: "Première tâche à faire", done: true},
{text: "Deuxième tâche", done: false},
{text: "Dernière tâche", done: false}
];

Code du composant

Le code du composant est représenté ici.

function TodoList({todos}) {
const {div, form, fieldset, input, span, button} = Room.elements();

const addTodo = e => {
todos.push({text: e.target[0].value, done: false});
return false;
};
const todoElement = (todo, i) => form(
{onSubmit: () => (todos.splice(i, 1), false)},
fieldset(
input({
type: "checkbox",
checked: () => todo.done,
onChange: e => todo.done = e.target.checked
}),
input({
type: "text",
value: () => todo.text,
disabled: () => todo.done,
onInput: e => todo.text = e.target.value
}),
span("[", () => i + 1, "]")
),
button("Supprimer")
);

return div({class: "todoListBlock"},
form({onSubmit: addTodo},
input({type: "text", required: true}),
button("Ajouter")
),
Room.map(div({class: "todoList"}), todos, todoElement)
);
}

Le composant retourne un élément <div> de classe todoListBlock contenant un élément <form> et un élément <div> de classe todoList.

L’élément <form> contient le champ pour saisir le nom d’une tâche et un bouton de soumission. L’élément <div> de classe todoList contient la liste des tâches, il est entièrement géré par la fonction map() de Room.

La fonction addTodo() sert de gestionnaire d’évènement pour l’évènement submit de l’élément <form> et ajoute simplement un nouvel élément à la fin du tableau todos.

La fonction todoElement() est utilisée par la fonction map() de Room pour produire un élément <form> contenant la représentation d’une tâche à faire avec une case à cocher pour modifier l’état de la tâche, un élément <input> pour modifier le texte de la tâche, un élément <span> contenant le numéro de la tâche et un bouton de soumission pour supprimer la tâche.

Il est à noter que les fonctions des attributs onSubmit des éléments <form> retournent false, ce qui fait que la soumission des formulaires ne fait pas son action par défaut. Cette facilité est décrite dans la fonction append() de Room.

Utilisation du composant

Pour utiliser ce composant, une donnée observable todos doit être créée avec la fonction createData() de Room et passée au composant. Afin de conserver la liste, elle est enregistrée dans le localStorage.

La liste est chargée depuis le localStorage après la création de la donnée todos et lui est affectée avec la fonction setData() de Room.

Pour enregistrer la liste, une fonction save() est attribuée à l’élément <div> contenant le composant pour les évènements unmount et pageHide. La fonction récupère la liste brute sans Proxy avec la fonction getData() de Room, elle est transformée en JSON qui est ajouté dans le localStorage.

La liste est ainsi sauvegardée quand le composant est supprimé du DOM ou en cas de rechargement de la page.

Afin de montrer la réactivité dans plusieurs composants utilisant une donnée observable identique, le composant est placé 2 fois dans l’élément <div>. Ainsi toutes les modifications réalisées dans un composant sont reportées dans l’autre.

Ceci donne les lignes de code suivantes :

const {div} = Room.elements();
const todos = Room.createData([]);
const name = "TodoList";
try {
Room.setData(todos, JSON.parse(localStorage.getItem(name)) || todos);
} catch(e) {};
const save = () => {
try {
localStorage.setItem(name, JSON.stringify(Room.getData(todos)));
} catch(e) {}
};
element.append(div({onUnmount: save, onPageHide: save},
TodoList({todos}),
TodoList({todos})
));

Et le résultat est le suivant :

Dernière mise à jour :