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.
Interface

SettingsDialog et contrôle Switch

Créez des boîtes de dialogue de paramètres à deux panneaux et des interrupteurs à bascule dans vos scripts client Dodock.

SettingsDialog et contrôle Switch

Dodock met à disposition deux primitives réutilisables côté client pour construire des interfaces de configuration soignées : frappe.ui.SettingsDialog pour les boîtes de dialogue à onglets et ControlSwitch pour les interrupteurs à bascule.

SettingsDialog

frappe.ui.SettingsDialog génère une boîte de dialogue modale composée de deux zones :

  • Un rail vertical d'onglets (sidebar à gauche) avec regroupement par catégorie.
  • Un panneau de contenu (droite) chargé à la demande à chaque activation d'onglet.

Elle hérite de frappe.ui.Dialog, ce qui lui donne la gestion du cycle de vie modal (fond semi-transparent, ouverture/fermeture, touche Échap, pile des dialogues ouverts).

Exemple minimal

new frappe.ui.SettingsDialog({
  title: __("Paramètres"),
  default_tab: "preferences",
  tabs: [
    {
      group: __("Configuration"),
      items: [
        {
          id: "preferences",
          label: __("Préférences"),
          icon: "sliders-vertical",
          title: __("Préférences"),
          description: __("Gérez vos préférences"),
          fields: [
            {
              fieldname: "theme",
              fieldtype: "Select",
              label: __("Thème"),
              options: "Clair\nSombre",
            },
          ],
          actions: [
            {
              label: __("Enregistrer"),
              variant: "solid",
              click(panel) {
                const values = panel.get_values(); // null si un champ requis est vide
                if (!values) return;
                // traiter values.theme …
              },
            },
          ],
        },
      ],
    },
  ],
}).show();

Structure de configuration

Clé (racine)TypeDescription
titlestringTitre affiché en haut de la boîte de dialogue
default_tabstringid de l'onglet actif à l'ouverture
tabsArrayListe des groupes d'onglets (voir ci-dessous)

Groupe d'onglets (tabs[].group) : libellé de section dans la sidebar.

Élément d'onglet (tabs[].items[]) :

CléTypeDescription
idstringIdentifiant unique de l'onglet
labelstringLibellé affiché dans la sidebar
iconstringNom d'icône du sprite, rendu par frappe.utils.icon (ex. "sliders-vertical")
icon_htmlstringHTML d'icône brut, prioritaire sur icon. Réservé à du HTML écrit par le développeur : ne le remplissez jamais avec une réponse serveur ou une saisie utilisateur
titlestringTitre affiché en en-tête du panneau
descriptionstringSous-titre affiché sous le titre
fieldsArrayChamps FieldGroup (même format que frappe.ui.Dialog)
actionsArrayBoutons d'action (voir ci-dessous)
render(panel)functionRendu personnalisé dans panel.body
on_activate(panel)functionAppelée à chaque activation de l'onglet

Action (actions[]) :

CléTypeDescription
labelstringLibellé du bouton
iconstringIcône du bouton
variantstringVariante du bouton frappe.ui.button, par exemple "solid" pour l'action principale
themestringThème du bouton, par exemple "red" pour une action destructive
classstringClasses CSS supplémentaires
click(panel)functionAppelée au clic. Elle reçoit le contrôleur SettingsDialogPanel, aussi disponible dans this

API du panneau (SettingsDialogPanel)

Chaque onglet est piloté par un contrôleur SettingsDialogPanel transmis aux fonctions render et actions[].click. Il expose :

MéthodeDescription
panel.get_values()Retourne les valeurs du formulaire, ou null si un champ requis est vide. Sans champs, retourne {}
panel.get_value(fieldname)Retourne la valeur d'un champ
panel.set_values(values)Injecte des valeurs dans le formulaire. Retourne une promesse
panel.get_field(fieldname)Retourne le contrôle d'un champ
panel.set_view(spec)Remplace en une fois l'en-tête, les actions et le formulaire
panel.refresh()Réinitialise le panneau à la vue définie dans la config de l'onglet
panel.set_header({ title, description, actions })Met à jour uniquement l'en-tête et ses actions
panel.add_fields(fields)Ajoute des champs au FieldGroup existant
panel.bodyÉlément jQuery du corps du panneau (disponible dans render)
panel.fieldgroupLe FieldGroup sous-jacent, ou null
panel.dialogL'instance SettingsDialog

Méthodes de la boîte de dialogue

MéthodeDescription
dialog.activate(id)Active l'onglet id. Le panneau est créé à la première activation, puis conservé avec son état
dialog.get_panel(id)Retourne le panneau d'un onglet déjà activé
dialog.reset(tabs, default_tab)Remplace les onglets sans recréer la fenêtre. L'état des panneaux est effacé

Sans default_tab, le premier onglet du premier groupe est activé. La boîte de dialogue a la taille extra-large par défaut. Elle n'affiche pas la barre de titre standard : chaque panneau a son propre en-tête.

panel.set_view(spec) permet d'implémenter une navigation à plusieurs niveaux (liste → formulaire → confirmation) sans coordination externe. Chaque appel remplace l'ensemble de la vue (en-tête + actions + formulaire) et les actions de la nouvelle vue lisent toujours le formulaire qui leur est colocalisé.

render(panel) {
  // Vue « liste »
  panel.set_view({
    title: __("Choisir un profil"),
    description: "",
    actions: [
      {
        label: __("Nouveau profil"),
        variant: "solid",
        click(p) {
          p.set_view({
            title: __("Nouveau profil"),
            fields: [{ fieldname: "nom", fieldtype: "Data", label: __("Nom"), reqd: 1 }],
            actions: [
              {
                label: __("Enregistrer"),
                variant: "solid",
                click(p2) {
                  const v = p2.get_values();
                  if (!v) return;
                  // sauvegarder v.nom …
                  p2.refresh(); // retour à la vue initiale
                },
              },
            ],
          });
        },
      },
    ],
    render(p) {
      p.body.append("<p>Aucun profil enregistré.</p>");
    },
  });
},

Flux d'instanciation


Contrôle Switch (fieldtype: "Switch")

Le contrôle Switch est un interrupteur à bascule (toggle) visuel qui remplace un simple bouton à cocher. Il peut être utilisé partout où un contrôle est instancié : FieldGroup, Dialog, formulaire de script client.

Caractéristiques

  • Héritage : sous-classe de ControlCheck — conserve un vrai <input type="checkbox"> et toute la sémantique 0/1 (get_values() retourne 1 ou 0).
  • Sémantique : validation, état lecture seule, reqd fonctionnent identiquement à ControlCheck.
  • Accessibilité : role="switch" sur la case à cocher. La case à cocher est masquée visuellement (motif « sr-only » : clip, clip-path, overflow) mais reste focalisable. Le libellé reste visible.
  • Interaction : toute la ligne est une <label> — cliquer n'importe où sur la ligne bascule l'état.
  • Style : la piste est rendue en CSS pur via :has(input:checked) pour les états cochés, survolés, ciblés et désactivés.

Utilisation dans un Dialog ou FieldGroup

const d = new frappe.ui.Dialog({
  title: __("Options"),
  fields: [
    {
      fieldname: "notifications_actives",
      fieldtype: "Switch",
      label: __("Activer les notifications"),
    },
    {
      fieldname: "mode_sombre",
      fieldtype: "Switch",
      label: __("Mode sombre"),
      default: 1,
    },
  ],
  primary_action_label: __("Enregistrer"),
  primary_action(values) {
    // values.notifications_actives → 1 ou 0
    // values.mode_sombre          → 1 ou 0
    d.hide();
  },
});
d.show();

Utilisation dans une SettingsDialog

new frappe.ui.SettingsDialog({
  title: __("Préférences"),
  default_tab: "affichage",
  tabs: [
    {
      group: __("Interface"),
      items: [
        {
          id: "affichage",
          label: __("Affichage"),
          icon: "eye",
          title: __("Affichage"),
          fields: [
            {
              fieldname: "compact",
              fieldtype: "Switch",
              label: __("Vue compacte"),
            },
          ],
          actions: [
            {
              label: __("Appliquer"),
              variant: "solid",
              click(panel) {
                const v = panel.get_values();
                if (!v) return;
                frappe.show_alert(v.compact ? __("Vue compacte activée") : __("Vue standard"));
              },
            },
          ],
        },
      ],
    },
  ],
}).show();

Comparaison Check / Switch

CritèreCheckSwitch
Valeur retournée1 / 01 / 0
RenduCase à cocher nativePiste coulissante
Accessibilitétype="checkbox"type="checkbox" + role="switch"
Cible de clicCase uniquementToute la ligne
InterchangeableOuiOui (même API)