Дочерний элемент LWC кэширует устаревшие данные с помощью запроса @wired Apex, родительский элемент не может обновитьApex () для дочернего элемента с помощью querySelector (), поскольку дочерний элемент скрыт с помощью if: true. Что делать?
Краткая структура приложения (см. изображение): справа список дочерних компонентов «Линия» (на фото всего один 1601xCC5Bulk), слева контейнер с поддонами. << Allocate btn открывает другой дочерний модальный файл с формой (if: true ..). В раскрывающемся списке этой формы используется @wire apex для отображения только пустых поддонов, поэтому он обновляется самим контроллером формы после DML.

Проблема возникает при изменении количества поддонов родителем, например, с помощью красной кнопки справа. этот DML удаляет контейнер вместе с поддонами.
Но если скрытая форма снова открывается, старые значения поддонов все еще присутствуют в качестве значений раскрывающегося списка, мне нужно обновить эти данные. но этот дочерний элемент скрыт, поэтому по стандарту недоступен: parent -> querySelector (child2) .method ()
- Извините за новый вопрос: есть ли способ получить доступ к скрытым методам компонента?
- Я также думал о том, чтобы переместить вызов Apex-запроса в родительский компонент (легко запустить), а затем передать его дочернему модальному модулю в качестве аргумента api, поэтому при появлении модального окна будут обновляться данные. это кажется немного неправильным, поскольку родители снимают бремя с ребенка (возможно, я ошибаюсь)
- Я также думал об использовании дочернего renderedCallback для этого запроса вершины, но боюсь бесконечных циклов рендеринга?
- Отключение кеширования auraEnabled apex было бы неплохо, но кажется невозможным.
Вот простая разметка, показывающая только все задействованные части
=== РОДИТЕЛЬ (с 2 детьми) ===
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;
}
=== РЕБЕНОК 1: упаковка-список-строка-элемент-карточка === (тот, что справа, показывает детали продукта, передает идентификатор в модальное окно)
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);
}
=== РЕБЕНОК 2: модальное распределение (условное отображение) ===
HTML
<template if:true={showInsertButton}>
<button class="slds-button slds-button_brand" onclick={handleAllocationInsert}>Insert</button>
</template>
JS (вас, вероятно, интересует только closeModal () {}, остальное - для полноты)
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();
}
Ответы
Извините за новый вопрос: есть ли способ получить доступ к скрытым методам компонента?
Нет . Ребенок не физически удаляется из DOM и больше не существует вообще (кроме , возможно , в компоненте кэша).
Я также думал о том, чтобы переместить вызов Apex-запроса в родительский компонент (легко запустить), а затем передать его дочернему модальному модулю в качестве аргумента api, поэтому при появлении модального окна будут обновляться данные. это кажется немного неправильным, поскольку родители снимают бремя с ребенка (возможно, я ошибаюсь)
На самом деле это очень стандартный способ сделать это. Ребенку нужно беспокоиться только о том, чтобы показать данные, для чего он предназначен. Как правило, рекомендуется получать / устанавливать данные как можно выше в иерархии компонентов (но не выше, чем необходимо).
Я также думал об использовании дочернего renderedCallback для этого запроса вершины, но боюсь бесконечных циклов рендеринга?
Плохая идея, вы получите бесконечные циклы, как и ожидаете. Однако здесь может иметь смысл использование connectedCallback компонента. Это событие вызывается только тогда, когда компонент добавляется или перемещается в DOM, поэтому у него не будет проблем с бесконечным циклом.
Отключение кеширования auraEnabled apex было бы неплохо, но кажется невозможным.
Это вполне возможно, но я считаю это последним средством. В большинстве случаев данные не меняются, пока пользователь что-то не сделает, поэтому кеширование может повысить производительность. Тем не менее, ваш дизайн, похоже, не требует частых вызовов, поэтому отключение кеширования, вероятно, также приемлемо.
В заключение я бы сказал, что управление данными от родителя было бы самым простым решением. Это также общеприемлемое решение в большинстве случаев, поскольку дочерние компоненты обычно работают только с данными, которые им переданы от родителя. Например, lightning-input
ничего не делает с сервером напрямую, но передает изменения родительскому объекту через события. Это совершенно естественный дизайн.
Если вы хотите, чтобы дети продолжали выполнять работу, это тоже нормально, просто вызовите refreshApex в своем connectedCallback или отключите кеширование. Любой из них должен решить вашу проблему, хотя вы можете протестировать на большом наборе данных, чтобы увидеть, какие из доступных вам вариантов предлагают наилучшую производительность.