Как я могу получить дочерние элементы из QueryList в Angular 2?

Я новичок в Angular2. На мой взгляд, у меня есть несколько идентичных потомков, которые генерируются в * ngFor.

<ngb-panel *ngFor="let client of clients" [title]="'Client #' + client.id">
    <template ngbPanelContent>
        <processing-item [client]="client"></processing-item>
    </template>
</ngb-panel>

Мне нужно вызвать методы этих компонентов в родительском элементе и узнать декоратор ViewChildren, а код следующий:

@ViewChildren(ProcessingItemComponent) processingItems: QueryList<ProcessingItemComponent>;

Затем я пытаюсь повторить их с помощью forEach:

ngAfterViewInit() {
    this.processingItems.forEach(function (el) {
        console.log(el);
    });
}

Но ничего не делает. Метод toArray (), вызываемый в QueryList, возвращает пустой массив.

Любые предложения, как я могу получить все дочерние компоненты одновременно и вызвать его методы?


person Anna Ladyzhenskaya    schedule 16.08.2017    source источник
comment
вы можете установить плункер?   -  person Max Koretskyi    schedule 16.08.2017


Ответы (2)


Если clients устанавливается из асинхронного вызова (например, на сервер), тогда элементы еще не существуют в ngAfterViewInit().

Ты можешь использовать

ngAfterViewInit() {
  this.processingItems.changes.subscribe(() => {
    this.processingItems.toArray().forEach(el => {
        console.log(el);
    });
  });
}

См. Также https://angular.io/api/core/QueryList#changes.

person Günter Zöchbauer    schedule 16.08.2017
comment
Проблема в том, что processingItems каким-то образом нельзя итерировать, но он существует. Когда я пытаюсь зарегистрировать этот элемент, я получаю следующее: joxi.ru/Dr8OEypCkMeY0A - person Anna Ladyzhenskaya; 16.08.2017
comment
Извините, я забыл добавить toArray() - person Günter Zöchbauer; 16.08.2017
comment
Он не измеряет, processingItems существует и имеет массив дочерних элементов в _result, но toArray () возвращает пустой массив :( - person Anna Ladyzhenskaya; 16.08.2017
comment
Даже в subscribe(...)? На вашем снимке экрана показано, что было найдено 5 элементов, toArray() обязательно должен вернуть массив, содержащий эти элементы. Можете ли вы воспроизвести в Plunker? - person Günter Zöchbauer; 16.08.2017
comment
Я думаю, вы имеете в виду this.processingItems.changes.subscribe(...). :-) - person Pengyy; 16.08.2017
comment
@Pengyy, ты прав. Большое спасибо. В отпуске память распалась: - / - person Günter Zöchbauer; 16.08.2017
comment
@ АннаЛадыженская интересно, а вы не получали ошибку при прямом звонке subscribe() на this.processingItems? - person Günter Zöchbauer; 16.08.2017
comment
@ GünterZöchbauer да, я получил ошибку, что subscribe () не является функцией, но я подумал, что, возможно, я сделал что-то не так - person Anna Ladyzhenskaya; 16.08.2017
comment
@ АннаЛадыженская Понятно. Простите за неудобства. Я был так уверен, что не стал проверять документы: - / - person Günter Zöchbauer; 16.08.2017
comment
@ GünterZöchbauer Тем не менее, спасибо, я бы не стал думать о Observable в одиночку) - person Anna Ladyzhenskaya; 16.08.2017

Я думаю, вам следует использовать атрибут @ContentChildren вместо ViewChildren.

@ContentChildren( OptionComponent )
public Options: QueryList<OptionComponent>;
person Matthew Parton    schedule 06.09.2018
comment
Не могли бы вы пояснить почему? - person Stefan Falk; 10.09.2018
comment
Извините, Стефан, то, что я хотел сказать, не вписывается в комментарий, поэтому я добавил его в качестве ответа ниже - person Matthew Parton; 12.09.2018
comment
Из приведенного выше кода в исходном вопросе я предполагаю, что пользователь желает использовать синтаксис шаблона и проекцию контента. Я считаю, что в этом случае ContentChildren работает лучше и вернет элементы. Вы также можете поместить ‹template› как ‹ng-content›, возможно. - person Matthew Parton; 12.09.2018
comment
На самом деле это неверно для данного вопроса. В вопросе она создает компоненты «на месте» в том же компоненте, в котором размещается ViewChildren. Таким образом, это не внедренное содержимое из родительского компонента, но она хочет получить ссылку на список дочерних элементов, созданных в этом компоненте через ngFor. - person Simon_Weaver; 02.03.2019
comment
Simon_Weaver прав, но проголосовал за, потому что у меня была аналогичная проблема, когда .toArray() возвращался пустым. Решение Гюнтера работало, но моя основная проблема заключалась в том, что родительский контейнер передавал элементы, а я использовал ViewChildren. Переход на ContentChildren позволил мне удалить логику подписки из ответа Гюнтера. - person Kevin; 01.07.2019