Accueil
NexoPOS

Ajouter un bouton « Créer » sur la sélection de recherche

Un « search-select » est un composant qui aide à filtrer une liste d’options et à faciliter la sélection. Par défaut, le composant n’autorise pas la création de nouvelles entrées qui seraient ensuite ajoutées à la liste des options. Avec quelques configurations, vous pouvez ajouter la prise en charge de la création d’entrées via une fenêtre contextuelle et, après une soumission réussie, les ajouter aux options.

Cette fonctionnalité fonctionne dès la sortie de la boîte avec les composants internes CRUD et de configuration, sans aucune modification de code supplémentaire. Cela signifie que, par exemple, si vous disposez d’un composant CRUD qui permet de sélectionner des produits, il vous suffit de définir la prise en charge sur le champ de sélection de recherche, c’est tout. En revanche, si vous souhaitez un contrôle plus approfondi ou mieux comprendre comment les choses sont faites, vous pouvez poursuivre la lecture.

Principe de fonctionnement

Un point important à noter est que vos implémentations doivent charger les champs de manière asynchrone. Cela garantit que les champs peuvent être rechargés à tout moment sans recharger la page (c’est ainsi que les champs du composant CRUD sont chargés sur NexoPOS).

Maintenant, lorsque vous définissez vos structures de champ, vous les définirez côté backend. À partir de là, vous indiquerez quel composant il doit charger lorsque l’on clique sur le bouton « + », ainsi que les configurations qui seront transmises en tant que propriétés (c’est un composant Vue 3).

Configuration du champ

Tous les composants CRUD fournissent leur configuration sous forme de tableau via la méthode getFormConfig. Lorsque nous créons notre champ, nous devons fournir deux entrées supplémentaires : « component » et « props ». Le composant peut être n’importe quel composant que vous souhaitez.

Si vous souhaitez utiliser votre composant, vous devez d’abord le enregistrer. De plus, ce composant résout la réponse provenant d’un serveur (ce qui est utile pour sélectionner l’entrée qui a été créée automatiquement). Toutefois, dans notre exemple, nous utiliserons « nsCrudForm », un composant construit sur NexoPOS pour afficher un formulaire CRUD.

Voici comment vous définirez ensuite la configuration de votre champ de sélection de recherche.

<?php
use App\Crud\ProductCategoryCrud;

$fields = [
    [
        'type' => 'search-select',
        'name' => 'category_id',
        'label' => 'Assigned Category',
        'description' => 'any description you want goes here',
        //  here is how to enable a support for a create button
        'component' => 'nsCrudForm',
        'props' => ProductCategoryCrud::getFormConfig()
    ]
];

Vous remarquerez que nous utilisons la classe ProductCategoryCrud pour récupérer sa configuration. À partir de NexoPOS 5, cette méthode est fournie à tous les composants CRUD disponibles. La variable $fields doit ensuite être renvoyée en réponse lors d’un appel API.

Configurer le composant Vue

Supposons que vous n’utilisiez pas nos composants nsSettings ou nsCrudForm. Dans ce cas, vous devrez mettre en place un pont de communication entre votre composant Vue qui rend le formulaire, le champ de recherche-sélection, et le composant utilisé pour créer une entrée. Comme vous pouvez l’imaginer, nous avons 3 composants Vue dans ce scénario. Nous commencerons par le composant qui rend le formulaire.

<template>
  <div>
    <form>
      <ns-field v-for="field in fields"/>
    </form>
  </div>
</template>

<script lang="ts">
declare const FormValidation;
export default {
  data() {
    return {
      fields: [],
      formValidation: new FormValidation,
    };
  },
  methods; {
    loadFields() {
      nsHttpClient('/api/path/to/the/fields')
        .subscribe({
          next: fields => {
            this.fields = this.formValidataion.createForm(fields);
          },
          error: error => {
            // handle error here
          });
    }
  }
  created() {
    this.loadFields();
  },
};
</script>

Comme mentionné ci-dessus, nous chargeons les champs de manière asynchrone. Maintenant, pour nous assurer de remplir les options, chaque fois que le composant qui crée l’entrée résout la réponse du serveur, nous devons ajouter une fonction de rappel à l’élément <ns-field> comme ceci :

<template>
  <div>
    <form>
      <ns-field @saved="handleSaveEvent( $event, field )" v-for="field in fields"/>
    </form>
  </div>
</template>

<script lang="ts">
declare const FormValidation;
export default {
  data() {
    return {
      fields: [],
      formValidation: new FormValidation,
    };
  },
  methods: {
    async handleSaveEvent( serverResponse, field ) {
      try {
        field.options.push({
            label: serverResponse.data.entry[ field.props.optionAttributes.label ],
            value: serverResponse.data.entry[ field.props.optionAttributes.value ]
        });
        field.value     =   serverResponse.data.entry[ field.props.optionAttributes.value ];
      } catch ( exception ) {
        // something went wrong
      }
      
    },
    loadFields() {
      return new Promise( ( resolve, reject ) => {
        nsHttpClient('/api/path/to/the/fields')
          .subscribe({
            next: fields => {
              resolve( fields );
              this.fields = this.formValidataion.createForm(fields);
            },
            error: error => {
              reject( error )
            });
      });
    }
  }
  created() {
    this.loadFields();
  },
};
</script>

Nous utilisons field.props pour obtenir la configuration réelle du composant Crud qui est en cours de chargement. Sur cet objet, nous avons « optionsAttributes », qui définissent quelle propriété doit être considérée comme un libellé ou quelle propriété doit être utilisée comme valeur. Notez que ces deux propriétés doivent être utilisées comme options. Par défaut, NexoPOS suppose que vous utilisez « id » comme valeur et « name » comme libellé. Vous pouvez modifier ce comportement en éditant « optionsAttributes » sur le composant crud.

Si vous n’utilisez pas nsCrudForm pour créer une entrée, nous allons vous montrer comment créer votre composant personnalisé, qui sera affiché dans une fenêtre contextuelle. Lorsqu’un composant est ouvert en tant que pop-up, NexoPOS fournit une prop supplémentaire, « popup ». Celle-ci peut ensuite être utilisée pour détecter s’il s’affiche dans une fenêtre contextuelle ou non. Voici comment nous allons définir notre composant :

<template>
  <div>
    <form>
      <ns-field v-for="field in fields"/>
      <button @click="createEntry()">Save</button>
    </form>
  </div>
</template>

<script lang="ts">
declare const FormValidation;
export default {
  props: [ 'popup' ],
  data() {
    return {
      fields: [],
      formValidation: new FormValidation,
    };
  },
  methods: {
    createEntry() {
      if ( this.formValidation.validateFields( this.fields ) ) {
          const form = this.formValidation.extractFields( this.fields );
          nsHttpClient.post( 'api/to/create/entry', form )
            .subscribe({
                next: response => {
                    this.popup.params.resolve( response );
                },
                error: error => {
                    this.popup.params.reject( error );
                }
            });
         return; // stop it here
      }
      
      // form is not valid
    },
    loadFields() {
      nsHttpClient('/api/path/to/the/fields')
        .subscribe({
          next: fields => {
            this.fields = this.formValidataion.createForm(fields);
          },
          error: error => {
            reject( error )
          });
    }
  }
  created() {
    this.loadFields();
  },
};
</script>

En utilisant la propriété « popup », nous avons accès à divers paramètres fournis à notre composant. Deux d’entre eux sont « resolve » et « reject ». Nous veillons à tous les deux à renvoyer la réponse du serveur.