Passer au contenu principal
Auth0 Dashboard > Actions > Forms > Champ personnalisé
Le champ personnalisé vous permet d’enrichir l’apparence de vos formulaires et d’ajouter une logique puissante avec JavaScript, HTML et CSS. Le champ personnalisé comprend des méthodes internes qui facilitent la transmission des données au formulaire, l’ajout de validations côté client et côté serveur, ainsi que la gestion d’événements courants comme le focus ou le blur. Vous pouvez utiliser un champ personnalisé pour créer :
  • Des champs avec une structure de données personnalisée.
    • Exemple : Objets, tableaux de chaînes
  • Des champs qui utilisent des widgets tiers.
    • Exemple : Saisie semi-automatique d’adresses Google
  • Des champs avec une logique permettant de masquer ou d’afficher d’autres champs.
  • Des champs qui nécessitent des API externes pour obtenir une valeur.
Pour utiliser des champs personnalisés, vous devez activer les domaines personnalisés. Le rendu d’un formulaire contenant un champ personnalisé en dehors d’un domaine personnalisé affichera une erreur.

Paramètres des champs personnalisés

Les paramètres des champs personnalisés sont :

Paramètres

Ajoutez des paires clé-valeur à utiliser dans le code source du champ personnalisé. Les paires clé-valeur peuvent inclure des variables de champ de formulaire.
Les valeurs des paramètres ne sont disponibles qu’après l’appel de la méthode init() par le formulaire.
Exemple : Dans l’exemple ci-dessous, les paramètres du champ personnalisé sont définis avec les paires clé-valeur symbol={{fields.symbol}} et separator=,
function CustomComponent(context) {
  const input = document.createElement('input');
  let mask = null;

  function mountComponent() {
    /** La méthode getParams() retourne les paramètres que vous avez configurés dans votre champ */
    const config = context.custom.getParams();
    const { symbol, separator } = config;

    mask = IMask(input,
    {
      mask: `${symbol}num`,
      blocks: {
        num: {
          mask: Number,
          thousandsSeparator: separator,
        }
      }
    });
  }

  return {
    /** Invoqué une seule fois lors de la création du champ */
    init() {
      mountComponent();
      return input;
    },
    ...
  };
}

Code source

Ajoutez votre code JavaScript dans le champ personnalisé.
Exemple:
function customInput() {
  const input = document.createElement('input');
  input.type = 'text';

  return {
    init() {
      return input;
    },

    block() {
      input.disabled = true;
    },

    unblock() {
      input.disabled = false;
    },

    getValue() {
      return input.value;
    }
  };
}

Schéma JSON

Par défaut, le champ personnalisé accepte les valeurs dans n’importe quel format. Cependant, vous pouvez utiliser JSON Schema pour valider les valeurs côté serveur.
Exemple:
{
  "type": "array",
  "items": {
    "type": "string"
  },
  "minItems": 2
}
Pour prendre en charge des exigences de validation complexes, vous pouvez utiliser un flux.

CSS

Ajoutez vos styles CSS dans le champ personnalisé.

Gestionnaires de champ personnalisés

Vous pouvez utiliser ces gestionnaires pour ajouter un comportement personnalisé au champ :

init()

Appelée une seule fois lors de la création du champ et reçoit les valeurs de params que vous configurez dans les paramètres paramètre. Retourne un élément HTML, une chaîne de caractères ou aucune valeur. Exemple:
const input = document.createElement('input');
input.type = 'text';

init() {
  return input;
}

update()

Appelée lorsque l’utilisateur revient à la même étape du formulaire. Cette option est utile lorsque vous devez réafficher la logique de l’interface utilisateur ou actualiser les valeurs des paramètres qui ont pu changer.

onFocus()

Appelée lorsque l’élément HTML du champ personnalisé reçoit le focus.

onBlur()

Appelé lorsque l’élément HTML du champ personnalisé perd le focus.

getValue()

Appelée lorsque le formulaire doit récupérer la valeur du champ personnalisé une ou plusieurs fois. Cela se produit généralement lorsque l’utilisateur soumet cette étape du formulaire. Si vous devez effectuer des validations côté client, vous pouvez générer une erreur pour afficher un message d’erreur personnalisé à l’utilisateur. Exemple :
function customTextInput() {
  const input = document.createElement('input');
  input.type = 'text';

  return {
    init() {
      return input;
    },

    getValue() {
      if (input.value !== 'Auth0') {
        throw new Error('The value must be Auth0')
      }

      return input.value;
    }
  };
}

block()

Appelée lorsque le champ personnalisé doit être bloqué. Cette fonction est généralement exécutée lorsque l’utilisateur soumet le formulaire à cette étape et que les données sont en cours de traitement par notre back-end.

unblock()

Appelée lorsque le champ personnalisé doit être débloqué. Cette méthode est généralement exécutée après que l’utilisateur a envoyé l’étape du formulaire ou que les données ont cessé d’être traitées par notre back-end en raison d’une erreur de validation.

getScripts()

Retourne une liste d’URL que le formulaire garantit avoir entièrement chargées avant d’appeler la méthode init(). Exemple:
getScripts() {
  return ['https://example.com/script_a.js', 'https://example.com/script_b.js'];
}

Objet de contexte

Lorsque vous passez un objet de contexte, vous pouvez utiliser ces méthodes pour gérer la logique de votre formulaire et de vos composants.

Méthodes personnalisées

context.custom.getValue()

Récupère la valeur du champ personnalisé actuel.

context.custom.setValue()

Définit une valeur pour le champ personnalisé courant. Exemple:
function customInput(context) {
  const input = document.createElement('input');
  input.type = 'text';

  input.addEventListener('change', () => {
    context.custom.setValue(input.value);
  });

  return {
    init() {
      return input;
    },
  };
}

context.custom.createUid()

Retourne un identifiant unique pour le champ personnalisé en cours. Exemple:
function customInput(context) {
  const input = document.createElement('input');
  input.type = 'text';
  input.id = context.custom.createUid();

  return {
    init() {
      return input;
    },

    getValue() {
      return input.value;
    }
  };
}

context.custom.getParams()

Reçoit les paramètres de configuration du champ personnalisé actuel.
Les valeurs des paramètres sont disponibles seulement après que le formulaire a appelé la méthode init().
Exemple:
function customInput(context) {
  // L'accès aux paramètres à la racine de la fonction ne fonctionne PAS
  // const { defaultValue } = context.custom.getParams();
  // console.log(defaultValue); // undefined

  function buildInput() {
    const { defaultValue } = context.custom.getParams();
    const input = document.createElement('input');
    input.type = 'text';
    input.value = defaultValue;

    return input;
  }

  return {
    init() {
      return buildInput();
    },

    getValue() {
      return input.value;
    }
  };
}

Méthodes du formulaire

Lorsque vous devez interagir avec le formulaire pour obtenir les valeurs d’autres champs ou passer à d’autres étapes du formulaire, vous pouvez utiliser les méthodes de formulaire suivantes :

context.form.getId()

Renvoie un identifiant unique pour le formulaire actuel.

context.form.getRoot()

Retourne l’élément HTML racine du formulaire en cours.

context.form.goForward()

Passe à l’étape suivante du formulaire.

context.form.goPrevious()

Revient à l’étape précédente du formulaire.

context.form.isValid()

Renvoie une valeur booléenne indiquant si le formulaire réussit toutes les validations côté client.

context.form.validate()

Évalue les valeurs de champ existantes au moyen de la validation côté client avant de poursuivre. Si un champ ne passe pas la validation, un message d’erreur s’affiche.

context.form.getAllHiddenFields()

Renvoie un objet contenant toutes les valeurs des champs masqués.

context.form.setHiddenField(id, value)

Définit la valeur d’un champ caché.
ParamètreDescription
idString. L’ID du champ caché.
valueString. La valeur du champ caché.

context.form.getValues()

Retourne un objet contenant toutes les valeurs des champs, y compris les champs masqués.

context.form.getField(id)

Renvoie une instance du champ spécifié.
  • getNode() | true Renvoie l’élément HTML racine du champ.
  • getValue() Renvoie la valeur du champ.
  • setRequired(boolean) Définit ou supprime le caractère obligatoire du champ.
ParamètreDescription
id*String *. La valeur du champ ID.
Exemple:
const fullName = context.form.getField('full_name');
const fullNameValue = fullName.getValue();
console.log(fullNameValue); // Jean Dupont
setRequired() ne fait que définir ou supprimer le caractère obligatoire du champ côté client. Par exemple, si vous retirez le caractère obligatoire d’un champ, mais qu’il est marqué comme obligatoire dans les paramètres du champ, le formulaire renverra une erreur si le champ n’a aucune valeur.

Exemples de champs personnalisés

Les sections ci-dessous présentent des exemples de champs personnalisés que vous pouvez ajouter à vos formulaires :

Champ personnalisé de saisie par plage

Un champ personnalisé qui renvoie une valeur dans une plage prédéfinie.
Code source:
function rangeInput() {
  const input = document.createElement('input');
  input.type = 'range';
  input.min= '0';
  input.max= '100';
  input.value = '0';

  return {
    init() {
      return input;
    },

    getValue() {
      return input.value;
    }
  };
}

Champ personnalisé de couleur

Un champ personnalisé qui renvoie un code couleur hexadécimal.
Code source :
function colorInput() {
  const input = document.createElement('input');
  input.type = 'color';
  input.value = '#20c5a0';

  return {
    init() {
      return input;
    },

    getValue() {
      return input.value;
    },
  };
}

Champ personnalisé avec saisie semi-automatique utilisant des valeurs provenant d’une API

Un champ personnalisé qui renvoie une valeur de saisie semi-automatique à l’aide d’une API tierce.
Code source:
function textInputWithAutocomplete(context) {
  const input = document.createElement('input');
  input.type = 'text';

  function populateInputValue(json) {
    const { city } = json;

    input.value = city;
  }

  function fetchIpInfo() {
    const url = 'https://ipinfo.io/json';
    fetch(url)
      .then((res) => res.json())
      .then((json) => populateInputValue(json));
  }

  return {
    init() {
      fetchIpInfo();
      return input;
    },

    getValue() {
      return input.value;
    },
  };
}

Champ personnalisé avec liste déroulante dynamique utilisant des valeurs d’une API

Un champ personnalisé qui renvoie une valeur à partir d’une liste déroulante dynamique à l’aide d’une API tierce.
Code source:
function dynamicDropdown() {
  const select = document.createElement('select');
  select.classList.add('af-stringField-input');

  function buildOption(data) {
    const { name: { first } } = data;
    const option = document.createElement('option');
    option.value = first;
    option.innerText = first;

    return option;
  }

  function populateNames(json) {
    const { results } = json;

    results.forEach((o) => {
      const option = buildOption(o);

      select.appendChild(option);
    });
  }

  function fetchNames() {
    const url = 'https://randomuser.me/api/?results=10&inc=name';
    fetch(url)
      .then((res) => res.json())
      .then((json) => populateNames(json));
  }

  return {
    init() {
      fetchNames();
      return select;
    },

    getValue() {
      return select.value;
    },
  };
}

Champ personnalisé de saisie dynamique avec un bouton (+) pour ajouter d’autres champs

Un champ personnalisé qui permet aux utilisateurs d’ajouter d’autres champs.
Code source:
function DynamicInputs(context) {
  const DEFAULT_INITIAL_INPUTS = 2;
  const DEFAULT_PLACEHOLDER = 'jane.doe@example.com';
  const DEFAULT_ADD_BUTTON_TEXT = 'Add new item';
  const DEFAULT_INPUT_TYPE = 'email';
  const STATE_VALUE = {};
  const FIELD_ID = context.custom.createUid();
  let UUID_COUNTER = 0;
  let INPUTS_COUNTER = 0;

  const container = document.createElement('div');

  const inputsContainer = document.createElement('div');
  container.appendChild(inputsContainer);

  function buildAddNewItem() {
    const config = context.custom.getParams();
    const { add_button_text } = config;

    const ADD_BUTTON_TEXT = add_button_text || DEFAULT_ADD_BUTTON_TEXT;

    const addInputButton = document.createElement('button');
    addInputButton.type = 'button';
    addInputButton.classList.add('af-dynamic-input-add-button');
    addInputButton.id = `${FIELD_ID}_add-input-button`;
    addInputButton.onclick = buildInputContainer.bind(this);

    const addInputButtonIcon = document.createElement('span');
    addInputButtonIcon.classList.add('af-button', 'af-dynamic-input-add-button-icon');
    addInputButtonIcon.innerText = '+';

    const addInputButtonText = document.createElement('span');
    addInputButtonText.classList.add('af-dynamic-input-add-button-text');
    addInputButtonText.innerText = ADD_BUTTON_TEXT;

    addInputButton.appendChild(addInputButtonIcon);
    addInputButton.appendChild(addInputButtonText);
    container.appendChild(addInputButton);
  }

  function removeInput(container, input) {
    delete STATE_VALUE[input.name];
    container.remove();
  }

  function buildRemoveInputButton(container, input) {
    const button = document.createElement('button');
    button.type = 'button';
    button.classList.add('af-button', 'af-dynamic-input-remove-button');
    button.innerText = '-';
    button.onclick = removeInput.bind(this, container, input);

    INPUTS_COUNTER--;

    return button;
  }

  function buildInput() {
    const config = context.custom.getParams();
    const { placeholder, input_type } = config;

    const PLACEHOLDER = placeholder || DEFAULT_PLACEHOLDER;
    const INPUT_TYPE = input_type || DEFAULT_INPUT_TYPE;

    const input = document.createElement('input');
    input.type = INPUT_TYPE;
    input.placeholder = PLACEHOLDER;
    input.classList.add('af-stringField-input');
    input.name = `${FIELD_ID}_${UUID_COUNTER}`;
    input.id = input.name;
    input.addEventListener('change', () => {
      STATE_VALUE[input.name] = input.value;
    });

    UUID_COUNTER++;

    return input;
  }

  function buildInputContainer() {
    const container = document.createElement('div');
    container.classList.add('af-dynamic-input-container');

    const input = buildInput();
    container.appendChild(input);

    const removeButton = buildRemoveInputButton(container, input);
    container.appendChild(removeButton);

    inputsContainer.appendChild(container);

    INPUTS_COUNTER++;
  }

  function initComponent() {
    const config = context.custom.getParams();
    const { initial_inputs } = config;

    const INITIAL_INPUTS = initial_inputs || DEFAULT_INITIAL_INPUTS;
    INPUTS_COUNTER = INITIAL_INPUTS

    for (let i = 0; i < INITIAL_INPUTS; i++) {
      buildInputContainer();
    }
  }

  function blockFields(value) {
    const inputKeys = Object.keys(STATE_VALUE);

    inputKeys.forEach((o) => {
      const selector = document.getElementById(o);
      selector.disabled = value;
    });
  }

  return {
    init() {
      buildAddNewItem();
      initComponent();
      return container;
    },

    block() {
      blockFields(true);
    },

    unblock() {
      blockFields(false);
    },

    getValue() {
      return Object.values(STATE_VALUE);
    },
  };
}
Code CSS :
.af-button.af-dynamic-input-remove-button {
  width: 48px;
  color: var(--button-font-color);
  background: var(--button-background-color);
}

.af-dynamic-input-container {
  display: flex;
  margin-bottom: var(--spacing-1);
}

.af-dynamic-input-container input {
  margin-right: var(--spacing-1);
}

button.af-dynamic-input-add-button {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  margin-top: var(--spacing-1);
  display: inline-flex;
  cursor: pointer;
  align-items: center;
}

.af-button.af-dynamic-input-add-button-icon {
  background: var(--primary-color);
  width: 24px;
  padding: 0;
  height: 24px;
  border-radius: .3em;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #fff;
  margin-right: var(--spacing-1);
}

.af-dynamic-input-add-button-text {
  color: var(--label-font-color);
  font-size: var(--label-font-size);
}

.af-dynamic-input-add-button:focus {
  outline: none;
}

.af-dynamic-input-add-button:hover .af-button {
  transition: filter var(--transition-normal), box-shadow var(--transition-normal);
  filter: brightness(1.1);
  box-shadow: 0 0 0 var(--outline-width) var(--outline-color), 0px 4px 8px -4px var(--shadow-color), 0px 16px 24px var(--shadow-color);
}

.af-dynamic-input-add-button:focus .af-button {
  box-shadow: 0 0 0 var(--outline-width) var(--outline-color), 0px 4px 8px -4px var(--shadow-color), 0px 16px 24px var(--shadow-color);
}