L'enfant LWC met en cache les données périmées par la requête Apex @wired, Parent ne peut pas refreshApex () sur l'enfant par querySelector () car l'enfant est masqué par if: true. Que faire?
brève structure de l'application (voir l'image): liste des composants enfants "Élément de campagne" à droite (un seul 1601xCC5Bulk sur cette photo), conteneur avec des palettes à gauche. << Allocate btn ouvre un autre modal enfant avec un formulaire (si: true ..) La liste de sélection de ce formulaire utilise @wire apex pour afficher uniquement les palettes vides, donc il est actualisé par le contrôleur du formulaire lui-même après DML.
problème survient lors du changement de quantité de palettes par un parent par exemple, en utilisant le bouton rouge sur la droite. ce DML supprime le conteneur avec les palettes.
Mais si le formulaire masqué est à nouveau ouvert, les anciennes valeurs de palette sont toujours présentes en tant que valeurs de liste de sélection, je dois actualiser ces données. mais cet enfant est caché, donc inaccessible par standard: parent -> querySelector (child2) .method ()
- Désolé pour la nouvelle question: existe-t-il un moyen d'accéder aux méthodes des composants cachés?
- Je pensais également déplacer l'appel à la requête Apex vers le composant parent (facile à déclencher), puis le transmettre au modal enfant en tant qu'argument api, donc lorsque le modal apparaît, il obtiendra des données mises à jour. cela semble un peu mal à faire, car le parent soulève le fardeau de l'enfant (peut-être que je me trompe)
- Je pensais aussi à utiliser le rendu de Child pour cette requête apex, mais j'avais peur des boucles de rendu infinies?
- La désactivation de la mise en cache de l'apex auraEnabled serait une bonne chose, mais semble impossible.
Voici le balisage simple, montrant uniquement toutes les parties impliquées
=== PARENT (avec 2 enfants) ===
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;
}
=== ENFANT 1: liste de colisage-ligne-article-carte === (celui de droite, montrant les détails du produit, passe l'identifiant au 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);
}
=== ENFANT 2: Allocation Modal (affichage conditionnel) ===
HTML
<template if:true={showInsertButton}>
<button class="slds-button slds-button_brand" onclick={handleAllocationInsert}>Insert</button>
</template>
JS (vous n'êtes probablement intéressé que par closeModal () {}, d'autres choses sont pour l'exhaustivité)
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();
}
Réponses
Désolé pour la nouvelle question: existe-t-il un moyen d'accéder aux méthodes des composants cachés?
Non. L'enfant est physiquement supprimé du DOM et n'existe plus du tout (sauf éventuellement dans un cache de composants).
Je pensais également déplacer l'appel à la requête Apex vers le composant parent (facile à déclencher), puis le transmettre au modal enfant en tant qu'argument api, donc lorsque le modal apparaît, il obtiendra des données mises à jour. cela semble un peu mal à faire, car le parent soulève le fardeau de l'enfant (peut-être que je me trompe)
C'est en fait une manière très standard de faire cela. L'enfant n'a qu'à se soucier d'afficher les données, ce pour quoi il est conçu. C'est généralement une bonne idée d'obtenir / définir des données aussi haut que possible dans la hiérarchie des composants (mais pas plus haut que nécessaire).
Je pensais aussi à utiliser le rendu de Child pour cette requête apex, mais j'avais peur des boucles de rendu infinies?
Mauvaise idée, vous obtiendrez des boucles infinies, comme prévu. Cependant, utiliser le connectedCallback du composant pourrait avoir un sens ici. Cet événement n'est appelé que lorsqu'un composant est ajouté ou déplacé dans le DOM, il n'aurait donc pas de problèmes de boucle infinis.
La désactivation de la mise en cache de l'apex auraEnabled serait une bonne chose, mais semble impossible.
C'est parfaitement possible, mais je considérerais cela comme un dernier recours. La plupart du temps, les données ne changent pas tant que l'utilisateur n'a pas fait quelque chose, donc la mise en cache peut améliorer les performances. Cela dit, votre conception semble également ne pas nécessiter d'appels fréquents, donc la désactivation de la mise en cache est probablement également acceptable.
En conclusion, je dirais que contrôler les données du parent serait la solution la plus simple. C'est également la solution généralement acceptable dans la plupart des cas, car les composants enfants ne fonctionnent généralement qu'avec les données qui leur sont fournies par le parent. Par exemple, lightning-input
ne fait rien avec le serveur directement, mais communique les modifications au parent via des événements. C'est un design parfaitement naturel à utiliser.
Si vous voulez que les enfants continuent à faire le travail, c'est très bien aussi, ayez simplement un appel refreshApex dans votre connectedCallback, ou désactivez la mise en cache. L'un ou l'autre devrait résoudre votre problème, bien que vous souhaitiez peut-être tester sur un grand ensemble de données pour voir laquelle des options disponibles offre les meilleures performances.