LWC-Pass-Rückruffunktion dynamisch
Ich habe eine modale Komponente, in der ich Zwei-Tasten-Handler-Methoden übergebe, die Rückrufe sind.
Diese beiden Tasten sind mit einem Getter verbunden, mit der Absicht, dass ich sie überschreiben kann, was ich nur schwer tun kann.
Codebeispiel:
export default class CreateCaseApp extends LightningElement {
// Default button handlers
_saveHandler = {
cb: this._modalSaveHandler,
label: "Create Case",
variant: "brand",
};
_cancelHandler = {
cb: this._modalCancelHandler,
label: "Cancel",
variant: "netrual",
class: "btn-left",
};
/**
* Getter: Save handler callback and button props
*/
get saveHandler() {
return this._saveHandler;
}
/**
* Getter: Cancel handler callback and button props
*/
get cancelHandler() {
return this._cancelHandler;
}
/**
* Save event send to modal
* @param {*} event
*/
_modalSaveHandler = (event) => {
console.log("Save Clicked");
};
/**
* Handler event sent to modal
* @param {*} event
*/
_modalCancelHandler = (event) => {
console.log("Cancel Clicked");
};
// Questionable code below
/**
* Handler event sent to modal for override
* @param {*} event
*/
_modalOverrideHandler = (event) => {
console.log("Override Clicked");
};
onDispatchedEventFromChild(event) {
if (event.detail == "nodata") {
// Override save handler button
this._saveHandler = {
cb: this._modalOverrideHandler,
label: "Okay",
variant: "brand"
};
}
}
}
Im obigen Code übergeben die Initialen saveHandler()und cancelHandler()die Fat-Arrow-Methoden korrekt über die cbEigenschaft im Objekt. Ich kann auf diese Schaltflächen in der untergeordneten Komponente klicken und sie führen die Methode von diesem übergeordneten Element aus.
Im unteren Teil des Codes habe ich einen Ereignis-Listener onDispatchedEventFromChild(), der Daten von einer untergeordneten Komponente empfängt. Wenn die Logik in dieser Methode erfüllt ist, versuche ich, die _saveHandlerSchaltfläche zu überschreiben , indem ich sie mit einstelle this._saveHandler={...}.
Dadurch werden die Schaltflächendetails wie Beschriftung und Variante aktualisiert, aber wenn ich darauf klicke, wird der neue referenzierte Rückruf nicht ausgelöst.
Ist das möglich oder gehe ich das falsch an? Ich habe versucht, @trackdie beiden Variablen zu verwenden, aber das hat auch nicht funktioniert.
Bearbeiten:
HTML der übergeordneten Komponente
<template>
<c-modal
modal-header={modalHeader}
modal-save-handler={saveHandler}
>
<div
slot="modalContent"
class="modalContent slds-modal__content slds-p-around_medium"
>
<!-- Wrapper -->
<c-create-case-wrapper
contact-id={recordId}
onmodalheaderupdate={handleModalHeaderEvent}
onmodalhandlerupdate={handleModalHandlerEvent}
></c-create-case-wrapper>
<!-- Wrapper -->
</div>
</c-modal>
<!-- Main Modal Launch Button -->
<lightning-button
variant="brand"
label="Create Enterprise Case"
title="Create Enterprise Case"
onclick={handleClick}
class="slds-m-left_x-small"
></lightning-button>
<!-- Main Modal Launch Button -->
</template>
Das übergeordnete Element stellt den Rückruf für den Schaltflächenklick innerhalb der modalen Komponente bereit. Wenn Sie auf eine Schaltfläche klicken, führt das übergeordnete Element diese Methode aus (im übergeordneten Element).
In diesem Beispiel werden <c-create-case-wrapper>auch untergeordnete Komponenten basierend auf Logik geladen. Wenn bestimmte Logik in diesen Komponenten erfüllt ist, muss ich den Rückruf und die Beschriftung der Schaltfläche ändern. Hier würde ein Kind ein Ereignis an die Eltern senden, damit ich weiß, dass ich die Modal-Schaltfläche aktualisieren muss.
Ich nahm an, dass ich, da die Schaltfläche reaktiv über den Getter an das Modal übergeben wurde, dieses Objekt / diesen Rückruf einfach aktualisieren konnte, um seine Standardeinstellungen zu überschreiben. Dies funktioniert für die Label- und Varianteneigenschaften einwandfrei, da ein anderer / anderer Rückruf übergeben wird, der nicht funktioniert.
Antworten
Es gibt einige Möglichkeiten, um Ihre Anforderung zu erfüllen, wie unten erwähnt. Bitte beachten Sie, dass Code-Schnipsel auf dem Github-Repo basieren, auf das Sie hingewiesen haben, und dass Sie es daher bei Bedarf ein wenig anpassen müssen. Außerdem habe ich nur die Codefragmente angegeben, die hinzugefügt oder aktualisiert werden sollen (der Rest Ihres Codes bleibt unverändert).
Option 1:
Führen Sie in der übergeordneten Komponente ein privates boolesches Feld overrideSaveund eine Methode ein _modalSaveDefaultHandler. Aktualisieren Sie _modalSaveHandlerden auszuführenden Code basierend auf dem Booleschen Flag-Wert. Aktualisieren Sie den onDispatchedEventFromChildCode, um das Boolesche Flag basierend auf Ihren spezifischen Bedingungen umzuschalten. Jetzt erhält die untergeordnete modale Komponente den Rückrufverweis auf beide _modalSaveDefaultHandler& _modalOverrideHandlerdurch _modalSaveHandler.
overrideSave = false;
_modalSaveHandler = (event) => {
if(!this.overrideSave){
this._modalSaveDefaultHandler(event);
}
else{
this._modalOverrideHandler(event);
}
};
_modalSaveDefaultHandler = (event) => {
console.log("Save Clicked");
};
onDispatchedEventFromChild() {
if (event.detail == "nodata") {
this.overrideSave = true;
}
}
Option 2:
In der modalen Komponente HTML ist das Klickereignis wahrscheinlich so verkabelt <button class="slds-button slds-button_brand save" onclick={modalSaveHandler.cb}>. Ersetzen Sie dies durch <button data-id="modalSaveBtn" class="slds-button slds-button_brand save">. Beachten Sie, dass wir die deklarative Ereignisverdrahtung entfernt haben und dies stattdessen programmgesteuert tun werden. Außerdem haben wir ein data-Attribut eingefügt, um das spezifische Schaltflächenelement per Code abfragen zu können.
Führen Sie in der Modalkomponente JS ein neues privates Feld handleRefein, in dem der Verweis auf den Rückruf gespeichert wird. Ändern Sie die renderedCallbackMethode, um die Rückrufreferenz (von der modalSaveHandleröffentlichen Eigenschaft) an handleRefden Klickereignishandler auf der jeweiligen Schaltfläche zu übergeben, und fügen Sie ihn programmgesteuert hinzu. Fügen Sie eine neue öffentliche Methode hinzu, updateRegisteredEventdie von der übergeordneten Komponente aufgerufen wird. Diese Methode ist dafür verantwortlich, den alten Ereignis-Listener zu entfernen und einen neuen Ereignis-Listener hinzuzufügen.
handlerRef;
isFirstRender = true;
renderedCallback() {
if (this.isFirstRender) {
this.handlerRef = this.modalSaveHandler.cb;
this.template.querySelector('[data-id="modalSaveBtn"]').addEventListener('click', this.handlerRef);
this.isFirstRender = false;
}
}
@api updateRegisteredEvent(overrideFn) {
this.template.querySelector('[data-id="modalSaveBtn"]').removeEventListener('click', this.handlerRef);
this.template.querySelector('[data-id="modalSaveBtn"]').addEventListener('click', overrideFn);
}
Aktualisieren Sie in der übergeordneten Komponente JS den onDispatchedEventFromChildCode, um die öffentliche Methode der untergeordneten Komponente aufzurufen (übergeben Sie die Überschreibungsmethode als Eingabeparameter).
onDispatchedEventFromChild() {
if (event.detail == "nodata") {
// Override save handler button
this._saveHandler = {
label: "Okay",
variant: "brand"
};
this.template.querySelector('c-modal').updateRegisteredEvent(this._modalOverrideHandler);
}
}
Option 3:
Definieren Sie in der Modalkomponente JS die Ereignishandlermethoden und verknüpfen Sie sie onclickdeklarativ mit dem HTML- Attribut. Der Ereignishandlercode sollte die modalen Komponentendetails (oder Formulardetails) nur über ein benutzerdefiniertes Ereignis an die übergeordnete Komponente übergeben. Es ist also nicht bekannt, wie die Daten von der übergeordneten Komponente verarbeitet werden.
Schließen Sie in der übergeordneten Komponente Ereignishandler an, die den benutzerdefinierten Ereignissen entsprechen (von der modalen Komponente ausgelöst), und implementieren Sie Ihre benutzerdefinierte Logik in diesem Ereignishandler basierend auf Ihren Anforderungen (und den zu erfüllenden spezifischen Bedingungen).
Hier werden keine Codebeispiele bereitgestellt, da dies die einfache LWC-Methode für die Ereigniskommunikation ist und daher einfacher zu handhaben sein sollte. Ich würde vorschlagen, diesen Ansatz zu wählen, da er dem LWC-Standard entspricht, eine spezifische Funktion / Verantwortung für jede Komponente definiert und als wiederverwendbare Komponenten entwickelt werden kann.
Zusätzliche Informationen: In Ihrem aktuellen Code wird die RückruffunktionsaveHandlerwährend der Komponenteninitialisierungüber dieEigenschaft übergeben, und beide Komponenten durchlaufen Hooks für den verbundenen und gerenderten Rückruflebenszyklus. Die LWC-Init- und Render-Lifecycle-Hooks verbinden den Rückruf mit dem Klickereignis des Schaltflächenelements. Wenn dieonDispatchedEventFromChildAusführung den Rückruf über das Objektliteral (this._savehandler)aktualisiert, wird jedoch nur derrenderedCallbackLifecycle-Hook für beide Komponenten ausgeführt. Dadurch werden die UI-Elemente grundsätzlich neu bewertet und erneut gerendert, es wird jedoch nichts gegen den Rückruf der Verkabelung zum Schaltflächenklickereignis unternommen. Dies könnte daran liegen, wie die LWC-Ereignisregistrierung intern funktioniert.