Personnalisation des listes intégrées
Personnalisation des listes intégrées
frappe.ui.EmbeddedList affiche un tableau d'enregistrements dans un conteneur : un onglet de formulaire, une boîte de dialogue, une page. Le desk l'utilise par exemple dans la boîte Paramètres du DocType et dans le formulaire Rôle.
Le composant n'est pas dans le bundle principal du desk. Chargez-le avant de l'utiliser :
await frappe.require("embedded_list.bundle.js");
Afficher une liste
frappe.ui.form.on("Customer", {
async refresh(frm) {
await frappe.require("embedded_list.bundle.js");
const list = new frappe.ui.EmbeddedList({
wrapper: frm.fields_dict.contacts_html.$wrapper.empty(),
doctype: "Contact",
fields: ["name", "full_name", "email_id", "is_primary_contact"],
filters: [["Dynamic Link", "link_name", "=", frm.doc.name]],
show_search: false,
empty_message: __("Aucun contact"),
columns: [
{ label: __("Nom"), fieldname: "full_name", type: "link", route: (row) => ["Form", "Contact", row.name] },
{ label: __("Email"), fieldname: "email_id" },
{ label: __("Principal"), fieldname: "is_primary_contact", type: "check" },
],
});
list.refresh();
},
});
Exemple fictif : contacts_html est un champ HTML personnalisé du formulaire Client. Le filtre porte sur la table enfant Dynamic Link du contact. Appelez refresh() pour charger et afficher les lignes.
Options
| Option | Défaut | Rôle |
|---|---|---|
wrapper | — | Conteneur (élément ou jQuery). Obligatoire. |
doctype, fields, filters, order_by | fields: ["name"] | Requête frappe.db.get_list. Toutes les lignes sont chargées (limit: 0). |
get_data | — | Fonction qui renvoie une promesse de lignes. Remplace la requête par défaut. |
get_page | — | Fonction ({ start, page_length, txt }) qui renvoie une page de lignes. Active la pagination et la recherche côté serveur. |
page_size | 50 | Nombre de lignes affichées avant le bouton « Charger plus ». |
columns | [] | Colonnes du tableau (voir plus bas). |
show_search | true | Affiche la zone de recherche. Mettez false pour une liste courte et fixe. |
title, description | — | En-tête de la liste. |
add_button | — | { label, action(refresh) } : bouton d'ajout dans l'en-tête. |
on_row_click | — | Fonction appelée avec la ligne cliquée. |
empty_message, no_match_message, loading_message, error_message | textes standard | Messages des états vide, sans résultat, chargement et erreur. |
Colonnes
| Clé | Rôle |
|---|---|
label, fieldname | En-tête et champ affiché. Le texte est échappé. |
align | center ou right. |
type | check (coche), badge (avec color, texte ou fonction), link (avec route(row) ou url(row), et text(row) facultatif), actions. |
render(row) | Renvoie le HTML de la cellule. Échappez vous-même les valeurs. |
on_click(row) | Rend la cellule cliquable. |
Une colonne type: "actions" contient des boutons :
{
type: "actions",
actions: [
{ label: __("Supprimer"), icon: "trash-2", danger: true,
confirm: __("Supprimer {0} ?"), confirm_field: "full_name",
action: (row, refresh) => frappe.db.delete_doc("Contact", row.name).then(refresh) },
],
}
confirm ouvre une confirmation avant l'action. {0} est remplacé par la valeur de confirm_field. Une action danger a un bouton rouge.
Révéler un contenu au survol de la ligne
Placez la classe embedded-list-hover-reveal sur l'élément à masquer dans une cellule. Il devient visible quand la ligne est survolée ou qu'un de ses éléments a le focus clavier.
{ label: "", render: (row) => `<span class="embedded-list-hover-reveal">${__("Voir le détail")}</span>` }
Le masquage utilise visibility : la largeur de la cellule ne change pas. Sur un écran tactile (sans survol), le contenu reste toujours visible. Réservez ce comportement aux contenus secondaires.