„Schaltfläche „Erstellen“ auf Suchauswahl hinzufügen“
Eine „Search-Select“-Komponente ist ein Baustein, der 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 Erstellung von Einträgen über ein Pop-up unterstützen und diese nach erfolgreicher Übermittlung den Optionen hinzufügen.
Diese Funktion funktioniert out of the box mit internen CRUD- und Settings-Komponenten, ohne dass weitere Codeänderungen erforderlich sind. Das bedeutet: Wenn Sie beispielsweise eine CRUD-Komponente haben, mit der sich Produkte auswählen lassen, 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 haben möchten, wie die Dinge umgesetzt werden, sollten Sie weiter lesen.
Wirkungsprinzip
Ein wichtiger Punkt ist, dass Ihre Implementierungen Felder asynchron laden müssen. Dadurch können die Felder jederzeit neu geladen werden, ohne die Seite neu laden zu müssen (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 bereit, und zwar über die Methode „getFormConfig“. 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 du deine Komponente verwenden möchtest, musst du sie zuerst registrieren. Außerdem löst diese Komponente die Antwort von einem Server auf (was nützlich ist, um den automatisch erstellten Eintrag auszuwählen). In unserem Beispiel verwenden wir jedoch „nsCrudForm“, eine auf NexoPOS basierende Komponente, um ein CRUD-Formular darzustellen.
So definierst du anschließend die Konfiguration deines Search-Select-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 a 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 anschließend als Antwort auf einen API-Aufruf zurückgegeben werden.
Einrichten der Vue-Komponente
Angenommen, Sie verwenden nicht unsere nsSettings- oder nsCrudForm-Komponente. In diesem Fall müssen Sie eine Kommunikationsbrücke zwischen Ihrer Vue-Komponente, die das Formular rendert, dem search-select-Feld und der Komponente herstellen, 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 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 gibt es „optionsAttributes“, die festlegen, welche Eigenschaft als Label betrachtet werden soll bzw. welche als Wert verwendet werden soll. Beachten Sie, dass diese beiden Eigenschaften als Optionen verwendet werden müssen. Standardmäßig geht NexoPOS davon aus, dass „id“ als Wert und „name“ als Label verwendet wird. 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 einen zusätzlichen Prop „popup“ bereit. Damit können Sie erkennen, ob die Komponente 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 „popup“-Eigenschaft haben wir Zugriff auf verschiedene Parameter, die von unserer Komponente bereitgestellt werden. Zwei davon sind „resolve“ und „reject“. Wir stellen sicher, dass wir beide mit der Antwort des Servers zurückgeben.