Aggiungi pulsante Crea su selezione ricerca
Un “search-select” è un componente che aiuta a filtrare un elenco di opzioni e a facilitare la selezione. Per impostazione predefinita, il componente non consente di creare nuove voci che vengono poi aggiunte all’elenco delle opzioni. Con alcune configurazioni, puoi aggiungere il supporto per la creazione di voci tramite una finestra pop-up e, dopo l’invio con successo, aggiungerle alle opzioni.
Questa funzionalità funziona out of the box con componenti interni di CRUD e impostazioni, senza ulteriori modifiche al codice. Ciò significa che, ad esempio, se hai un componente CRUD che consente di selezionare prodotti, devi semplicemente definire il supporto sul campo search-select: tutto qui. Tuttavia, se vuoi avere un controllo più approfondito o una migliore comprensione di come vengono gestite le cose, potresti continuare a leggere.
Principio di funzionamento
Una cosa importante da notare è che le tue implementazioni devono caricare i campi in modo asincrono. Questo garantisce che i campi possano essere ricaricati in qualsiasi momento senza ricaricare la pagina (è così che vengono caricati i campi del componente CRUD su NexoPOS).
Ora, quando definisci le strutture del tuo campo, le definirai lato backend. Da lì, imposterai quale componente deve essere caricato quando viene cliccato il pulsante “+” e le configurazioni che vengono passate come proprietà (si tratta di un componente Vue 3).
Configurazione del campo
Tutti i componenti CRUD forniscono la loro configurazione come un array utilizzando il metodo getFormConfig. Quando creiamo il nostro campo, dobbiamo fornire due voci aggiuntive: "component" e "props". Il componente può essere qualsiasi componente desideri.
Se vuoi utilizzare il tuo componente, devi prima registrarlo. Inoltre, quel componente risolve la risposta proveniente da un server (cosa utile per selezionare la voce creata automaticamente). Tuttavia, nel nostro esempio, useremo “nsCrudForm”, un componente costruito su NexoPOS per visualizzare un form CRUD.
Ecco come definirai quindi la configurazione del campo di ricerca-selezione.
<?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()
]
];
Noterai che utilizziamo la classe ProductCategoryCrud per recuperare la sua configurazione. Da NexoPOS 5, questo metodo viene fornito a tutti i componenti CRUD disponibili. La variabile $fields deve quindi essere restituita come risposta in una chiamata API.
Impostare il componente Vue
Supponiamo che tu non stia utilizzando i nostri componenti nsSettings o nsCrudForm. In tal caso, dovrai fornire un ponte di comunicazione tra il tuo componente Vue che renderizza il form, il campo di ricerca-selezione e il componente utilizzato per creare una voce. Come puoi immaginare, in questo scenario abbiamo 3 componenti Vue. Inizieremo dal componente che renderizza il form.
<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>
Come indicato sopra, stiamo caricando i campi in modo asincrono. Ora, per assicurarsi di popolare le opzioni, ogni volta che il componente che crea la voce risolve la risposta dal server, dobbiamo aggiungere una callback all’elemento <ns-field> in questo modo:
<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>
Stiamo usando field.props per ottenere la configurazione effettiva del componente Crud che viene caricato. Su quell’oggetto, abbiamo “optionsAttributes”, che definiscono quale proprietà deve essere considerata come etichetta o quale deve essere usata come valore. Nota che queste due proprietà devono essere usate come opzioni. Per impostazione predefinita, NexoPOS assume che tu stia usando “id” come valore e “name” come etichetta. Puoi modificare questo comportamento modificando “optionsAttributes” sul componente crud.
Se non stai utilizzando nsCrudForm per creare una voce, ti mostreremo come creare la tua componente personalizzata che verrà visualizzata in una finestra pop-up. Quando una componente viene aperta come pop-up, NexoPOS fornisce una prop aggiuntiva, "popup". Questa può quindi essere utilizzata per rilevare se viene visualizzata in un pop-up o meno. Ecco come definiremo la nostra componente:
<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>
Utilizzando la proprietà “popup”, abbiamo accesso a vari parametri forniti al nostro componente. Due di questi parametri sono “resolve” e “reject”. Ci assicuriamo di entrambi per restituire la risposta del server.