Füge eine „Erstellen“-Schaltfläche in das Suchauswahl-Feld ein
Ein „Search-Select“ ist eine Komponente, die dabei hilft, eine Liste von Optionen zu filtern und die Auswahl zu erleichtern. Standardmäßig erlaubt die Komponente nicht, neue Einträge zu erstellen, die später der Liste der Optionen hinzugefügt werden. Mit einigen Konfigurationen können Sie die Unterstützung für das Erstellen von Einträgen über ein Popup hinzufügen und nach erfolgreicher Übermittlung dafür sorgen, dass diese den Optionen hinzugefügt werden.
Diese Funktion funktioniert out of the box mit internen CRUD- und Settings-Komponenten, ohne dass weitere Änderungen am Code erforderlich sind. Das bedeutet: Wenn Sie beispielsweise eine CRUD-Komponente haben, die das Auswählen von Produkten ermöglicht, müssen Sie lediglich die Unterstützung im Such-Auswahl-Feld definieren – das ist alles. Wenn Sie jedoch eine tiefere Kontrolle oder ein besseres Verständnis dafür möchten, wie die Dinge umgesetzt sind, sollten Sie weiterlesen.
Wirkprinzip
Ein wichtiger Punkt ist, dass Ihre Implementierungen die Felder asynchron laden müssen. Dadurch können die Felder jederzeit neu geladen werden, ohne dass die Seite neu geladen werden muss (so werden die Felder der CRUD-Komponente auf NexoPOS geladen).
Wenn Sie Ihre Feldstrukturen definieren, definieren Sie diese auf der Backend-Seite. Von dort aus legen Sie fest, welche Komponente geladen werden soll, wenn auf die „+“-Schaltfläche geklickt wird, sowie die Konfigurationen, die als Properties übergeben werden (es handelt sich um eine Vue-3-Komponente).
Feldkonfiguration
Alle CRUD-Komponenten stellen ihre Konfiguration als Array über die Methode „getFormConfig“ bereit. Wenn wir unser Feld erstellen, müssen wir zwei zusätzliche Einträge angeben: „component“ und „props“. Die Komponente kann jede beliebige Komponente sein, die Sie möchten.
Wenn Sie Ihre Komponente verwenden möchten, müssen Sie sie zuerst registrieren. Außerdem löst diese Komponente die Antwort von einem Server auf (was nützlich ist, um den Eintrag auszuwählen, der automatisch erstellt wurde). In unserem Beispiel werden wir jedoch „nsCrudForm“ verwenden – eine auf NexoPOS basierende Komponente, um ein CRUD-Formular darzustellen.
So definierst du dann die Konfiguration deines Suchauswahl-Felds.
<?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 support for a create button
'component' => 'nsCrudForm',
'props' => ProductCategoryCrud::getFormConfig()
]
];
Sie werden feststellen, dass wir die Klasse „ProductCategoryCrud“ verwenden, um ihre Konfiguration abzurufen. Ab NexoPOS 5 wird diese Methode allen verfügbaren CRUD-Komponenten bereitgestellt. Die Variable „$fields“ muss dann als Antwort auf einen API-Aufruf zurückgegeben werden.
Einrichten der Vue-Komponente
Angenommen, Sie verwenden weder unsere nsSettings- noch unsere nsCrudForm-Komponente. In diesem Fall müssen Sie eine Kommunikationsbrücke zwischen Ihrer Vue-Komponente, die das Formular rendert, dem Such-Auswahl-Feld und der Komponente bereitstellen, die zum Erstellen eines Eintrags verwendet wird. Wie Sie vielleicht vermuten, gibt es in diesem Szenario 3 Vue-Komponenten. Wir beginnen mit der Komponente, die das Formular rendert.
<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>
Wie oben erwähnt, laden wir die Felder asynchron. Damit die Optionen jedoch jedes Mal befüllt werden, wenn die Komponente, die den Eintrag erstellt, die Antwort vom Server erhält, müssen wir einen Callback an das Element „<ns-field>“ wie folgt hinzufügen:
<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>
Wir verwenden field.props, um die tatsächliche Konfiguration der geladenen Crud-Komponente zu erhalten. In diesem Objekt haben wir „optionsAttributes“, die festlegen, welche Eigenschaft als Bezeichnung dienen soll bzw. welche als Wert verwendet werden soll. Beachten Sie, dass diese beiden Eigenschaften zwingend als Option verwendet werden müssen. Standardmäßig geht NexoPOS davon aus, dass „id“ als Wert und „name“ als Bezeichnung verwendet werden. Sie können dieses Verhalten ändern, indem Sie „optionsAttributes“ in der Crud-Komponente bearbeiten.
Wenn Sie nsCrudForm nicht verwenden, um einen Eintrag zu erstellen, zeigen wir Ihnen, wie Sie Ihre benutzerdefinierte Komponente erstellen, die in einem Pop-up angezeigt wird. Wenn eine Komponente als Pop-up geöffnet wird, stellt NexoPOS als zusätzlichen Prop die Variable „popup“ bereit. Diese kann dann verwendet werden, um zu erkennen, ob sie in einem Pop-up angezeigt wird oder nicht. So definieren wir unsere Komponente:
<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>
Mithilfe der Eigenschaft „popup“ haben wir Zugriff auf verschiedene Parameter, die in unserer Komponente bereitgestellt werden. Zwei dieser Parameter sind „resolve“ und „reject“. Wir stellen sicher, dass beide die Antwort des Servers zurückgeben.