Version de développement
Cette documentation décrit la version « next » (develop), non encore publiée. Pour la version stable, basculez sur « v5 » dans l'en-tête.
Développeurs

Sections optionnelles

Afficher des sections de formulaire ajoutées à la demande avec le composant frappe.ui.OptionalSections.

Sections optionnelles

frappe.ui.OptionalSections affiche une rangée de boutons d'ajout, un par section optionnelle d'un formulaire. Cliquer sur un bouton affiche la section en ligne, avec un bouton de suppression qui la masque et remet son bouton d'ajout en place. Le composant convient aux formulaires dont la plupart des champs sont facultatifs : les champs obligatoires restent visibles et les autres n'apparaissent que sur demande.

Il est également exposé sous la forme pratique frappe.ui.optional_sections(opts), qui construit les sections et renvoie l'élément racine.

Une démonstration est disponible dans l'explorateur de composants du bureau (page « Component Explorer », entrée « Optional Sections »).

Prérequis

  • Le code s'exécute dans le bureau (desk), où frappe.ui.button est disponible : le composant construit ses boutons avec.
  • Les deux bundles optional_sections.bundle.js et optional_sections.bundle.css sont chargés avant l'appel.

Chargement

Le composant est distribué dans son propre bundle, chargé à la première utilisation afin de ne pas alourdir les bundles du bureau et du site :

await frappe.require(["optional_sections.bundle.js", "optional_sections.bundle.css"]);

Utilisation

await frappe.require(["optional_sections.bundle.js", "optional_sections.bundle.css"]);

const sections = new frappe.ui.OptionalSections({
    label: __("Ajouter d'autres informations"),
    sections: [
        { title: __("Contact"), content: () => this.make_contact_fields() },
        { title: __("Coordonnées bancaires"), content: () => this.make_bank_fields() },
    ],
    on_remove: (index) => this.clear_fields(index),
});
body.append(sections.$el);

La forme courte s'enchaîne directement dans un append :

body.append(
    frappe.ui.optional_sections({
        label: __("Ajouter d'autres informations"),
        sections: [{ title: __("Contact"), content: "Champs de contact ici." }],
    })
);

Options

OptionTypeDescription
sectionsArraySections optionnelles du formulaire, décrites ci-dessous.
labelstringTexte affiché au-dessus des boutons d'ajout, par exemple __("Ajouter d'autres informations").
remove_labelstringLibellé du bouton de suppression de chaque section. Par défaut : __("Remove").
on_addfunctionAppelée avec (index, section) après l'ajout d'une section.
on_removefunctionAppelée avec (index, section) après la suppression d'une section. La suppression masque la section mais conserve son contenu : réinitialisez vos champs dans ce rappel.
css_classstringClasses supplémentaires ajoutées à l'élément racine.

Chaque entrée de sections accepte les options suivantes :

OptionTypeDescription
titlestringIntitulé de la section, également utilisé comme libellé de son bouton d'ajout. Affiché comme texte, jamais comme HTML.
contentElement, JQuery, function ou stringCorps de la section. Une fonction est appelée avec l'instance du composant, une seule fois au premier affichage de la section, et doit renvoyer un élément. Une chaîne est affichée comme texte, jamais comme HTML.
addedbooleanAffiche la section dès le départ.

Comportement

  • Cliquer sur un bouton d'ajout affiche la section en ligne, dans l'ordre déclaré, et masque le bouton ; le bouton de suppression masque la section et remet le bouton d'ajout en place.
  • Le contenu d'une section n'est construit qu'à son premier affichage.
  • À l'ajout, le focus est placé sur le premier champ de la section (input autre qu'une case à cocher ou un champ caché, select ou textarea), ou à défaut sur le premier bouton de la section. À la suppression, le focus revient au bouton d'ajout.
  • La rangée des boutons d'ajout est masquée dès que toutes les sections sont ajoutées.
  • Chaque section porte l'attribut data-state="added" ou data-state="removed". La racine porte la classe es-optional-sections et les éléments internes suivent la convention es-optional-sections__* (par exemple es-optional-sections__buttons).
  • Les intitulés et les contenus textuels sont rendus comme du texte brut : le composant n'interprète jamais de HTML.

Exemple avec des champs

Lorsque la section contient des champs, construisez-les dans content et réinitialisez-les dans on_remove, car la suppression conserve le contenu :

let fields;

body.append(
    frappe.ui.optional_sections({
        label: __("Ajouter d'autres informations"),
        sections: [
            {
                title: __("Contact"),
                content: () => {
                    const section_body = document.createElement("div");
                    fields = new frappe.ui.FieldGroup({
                        body: section_body,
                        fields: [
                            { fieldtype: "Data", fieldname: "email", label: __("E-mail") },
                            { fieldtype: "Column Break", fieldname: "column" },
                            { fieldtype: "Data", fieldname: "mobile", label: __("Mobile") },
                        ],
                    });
                    fields.make();
                    return section_body;
                },
            },
        ],
        on_remove: () => fields.set_values({ email: "", mobile: "" }),
    })
);

Méthodes de l'instance

L'instance créée avec new frappe.ui.OptionalSections(opts) expose :

  • add(index) : affiche la section située à l'index donné.
  • remove(index) : masque la section située à l'index donné.
  • is_added(index) : renvoie true si la section est affichée.
  • destroy() : retire l'élément du DOM.
  • $el et el : l'élément racine, en jQuery et en élément DOM.

La forme pratique frappe.ui.optional_sections(opts) renvoie l'élément racine en jQuery ; l'instance reste accessible via .data("es-optional-sections") :

const $el = frappe.ui.optional_sections({ sections: [] });
const sections = $el.data("es-optional-sections");
sections.add(0);