Il figlio LWC memorizza nella cache i dati non aggiornati dalla query Apex @wired, Parent non può refreshApex () sul figlio da querySelector () perché il figlio è nascosto da if: true. Cosa fare?
breve struttura dell'app (vedi immagine): elenco dei componenti secondari "Elemento pubblicitario" a destra (solo un 1601xCC5Bulk in questa immagine), contenitore con pallet a sinistra. << Allocate btn apre un altro modale figlio con un modulo (if: true ..) l'elenco di selezione di questo modulo utilizza @wire apex per mostrare solo i pallet vuoti, quindi viene aggiornato dal controller del modulo stesso dopo DML.

Il problema sorge quando si cambia la quantità di pallet da un genitore, ad esempio, utilizzando il pulsante rosso a destra. questo DML cancella il container insieme ai pallet.
Ma se il modulo nascosto viene aperto di nuovo, i vecchi valori di pallet sono ancora presenti come valori di elenco di selezione, è necessario aggiornare i dati. ma questo bambino è nascosto, quindi irraggiungibile per standard: parent -> querySelector (child2) .method ()
- Ci scusiamo per la domanda newb: c'è un modo per accedere ai metodi dei componenti nascosti?
- Stavo anche pensando di spostare la chiamata alla query Apex fino al componente padre (facile da attivare), quindi passarla a child modal come argomento api, quindi quando appare modal riceverà dati aggiornati. questo sembra un po 'sbagliato da fare, poiché il genitore solleva il fardello del bambino.
- Stavo anche pensando di utilizzare il renderingCallback del bambino per quella query apex, ma hai paura dei loop di rendering infiniti?
- Disabilitare il caching di auraEnabled apex sarebbe una cosa carina, ma sembra impossibile.
Ecco il markup delle ossa nude, che mostra solo tutte le parti coinvolte
=== GENITORE (con 2 figli) ===
HTML
<template for:each={lineItems.data} for:item="lineItem">
<lightning-layout-item key={lineItem.Id} size="12">
<c-packing-list-line-item-card lineitem={lineItem} onallocatebuttonpress={openAllocationModal}></c-packing-list-line-item-card>
</lightning-layout-item>
</template>
<template if:true={isLineItemModalOpen}>
<c-packing-list-allocation-modal recordid={recordId} oncloseallocationmodal={closeAllocModal} onproductallocated={refreshData}></c-packing-list-allocation-modal>
</template>
JS
openAllocationModal(e) {
this.editItemId = e.detail;
this.isLineItemModalOpen = true;
}
closeAllocModal() {
this.isLineItemModalOpen = false;
}
=== BAMBINO 1: packing-list-line-item-card === (quello a destra, che mostra i dettagli del prodotto, passa l'id a modal)
HTML
<lightning-button variant="brand" label="<< Allocate" data-itemid={lineitem.Id} onclick={openAllocationModal}></lightning-button>
JS
openAllocationModal(e) {
const selectEvent = new CustomEvent('allocatebuttonpress', { detail: e.target.dataset.itemid });
this.dispatchEvent(selectEvent);
}
=== BAMBINO 2: Allocazione Modale (visualizzazione condizionale) ===
HTML
<template if:true={showInsertButton}>
<button class="slds-button slds-button_brand" onclick={handleAllocationInsert}>Insert</button>
</template>
JS (probabilmente sei interessato solo a closeModal () {}, altre cose sono per completezza)
handleAllocationInsert() {
[...]
createRecord(recordInput)
.then((allocId) => {
this.showToast('success', 'Success', 'Product Allocated');
this.handleInsert(this.palletValue);
this.refreshPallets();
})
.catch((error) => {
this.showToast('error', 'Error creating record', error.body.message);
this.closeModal();
});
}
closeModal() {
// On save parent closes modal
console.log('closing 1');
const selectEvent = new CustomEvent('closeallocationmodal');
this.dispatchEvent(selectEvent);
this.spinner = false;
}
handleInsert(palletValue) {
// On save parent refreshes container view
const selectEvent = new CustomEvent('productallocated', {
detail: this.palletcontainers[palletValue].containerId
});
this.dispatchEvent(selectEvent);
this.closeModal();
}
Risposte
Ci scusiamo per la domanda newb: c'è un modo per accedere ai metodi dei componenti nascosti?
No. Il bambino è fisicamente rimosso dal DOM e non esiste affatto (se non in una cache componente).
Stavo anche pensando di spostare la chiamata alla query Apex fino al componente padre (facile da attivare), quindi passarla a child modal come argomento api, quindi quando appare modal riceverà dati aggiornati. questo sembra un po 'sbagliato da fare, poiché il genitore solleva il fardello del bambino.
Questo è in realtà un modo molto standard per farlo. Il bambino deve solo preoccuparsi di mostrare i dati, che è ciò per cui è progettato. In genere è una buona idea ottenere / impostare i dati il più in alto possibile nella gerarchia dei componenti (ma non più in alto del necessario).
Stavo anche pensando di utilizzare il renderingCallback del bambino per quella query apex, ma hai paura dei loop di rendering infiniti?
Pessima idea, otterrai loop infiniti, come ti aspetti. Tuttavia, l'utilizzo di connectedCallback del componente potrebbe avere senso qui. Questo evento viene chiamato solo quando un componente viene aggiunto o spostato nel DOM, quindi non avrebbe problemi di loop infiniti.
Disabilitare il caching di auraEnabled apex sarebbe una cosa carina, ma sembra impossibile.
È perfettamente possibile, ma lo considero l'ultima risorsa. Il più delle volte, i dati non cambiano fino a quando l'utente non fa qualcosa, quindi la memorizzazione nella cache può migliorare le prestazioni. Detto questo, anche il tuo progetto sembra non aver bisogno di chiamate frequenti, quindi la disabilitazione della cache è probabilmente accettabile.
In conclusione, direi che il controllo dei dati dal genitore sarebbe la soluzione più semplice. Questa è anche la soluzione generalmente accettabile nella maggior parte dei casi, poiché i componenti figlio in genere funzionano solo con i dati forniti dal genitore. Ad esempio, lightning-input
non fa nulla direttamente con il server, ma comunica le modifiche al genitore tramite eventi. È un design perfettamente naturale da usare.
Se vuoi che i bambini continuino a fare il lavoro, va bene anche questo, basta avere una chiamata refreshApex nel tuo connectedCallback o disabilitare la cache. Entrambi dovrebbero risolvere il problema, anche se potresti voler testare su un set di dati di grandi dimensioni per vedere quale delle opzioni disponibili offre le migliori prestazioni.