Установщик Angular 5 над @Input не работает

У меня есть проект на основе Angular 5. Допустим, у меня есть два компонента: ParentComponent и ChildComponent. ChildComponent имеет общедоступный сеттер с декоратором @Input(). Я передаю ему свойство из родительского компонента, которое будет изменено позже.

Моя проблема в том, что этот сеттер не работает с картами, интерфейсами, такими объектами, как

{ [ key: string ]: boolean }

только с массивами и примитивами.

Ну, это работает, но только один раз.

Я уже понимаю, что это что-то с типом данных, но кто может дать хорошее объяснение или ссылку на документы? Не нашел разрешенных типов данных на веб-сайте Angular с документами.

Что здесь не так?

Ссылка на плункер, если кому нужно: https://plnkr.co/edit/WBS55F3wZSYI0qGNEGSd?p=preview

Как видите, есть 3 сеттера, они работают в первый раз, потом работают только сеттеры Array и String. Почему?

Обновление: похоже, это работает, если я изменяю на карте какое-то значение по его ключу, который уже существует, но не работает, если я добавляю новую пару ключ => значение.


person WeekendMan    schedule 04.01.2018    source источник


Ответы (1)


Поля mapItemsData и arrayItemsData устанавливаются только один раз. Поле stringItemData устанавливается каждый раз, когда изменяется ссылка на объект, потому что это строковый тип, а строки неизменяемы. Строка this.stringItem += this.iterationValue.toString(); фактически создает новую ссылку на строку каждый раз, когда она вызывается, что приводит к повторному вызову установщика дочернего компонента с новым значением.


Причина, по которой вы не видите, что данные обновляются для mapItemsData, заключается в том, что вы не можете повторить их с помощью *ngFor, но если вы добавите это в свой шаблон, вы увидите, что тот же объект обновляется.

{{mapItems.size}}

Если вы хотите повторить коллекцию Map, вы можете сделать это, используя записи().

<div *ngFor="let item of mapItems.entries()">{{ item }}</div>

Для получения дополнительной информации о типе Map см. документация.


Вам также необходимо изменить код настройки, чтобы вы не указывали на другой (новый) экземпляр, а указывали на тот же экземпляр, на который ссылается ваш родительский (содержащий) компонент.

public set mapItemsData(set: Map<string, boolean>) {
    // this.mapItems = []; <- you were changing the reference here
    this.mapItems = set; // this is really all you need
}

Обновлен плункер

person Igor    schedule 04.01.2018
comment
Большое спасибо за подробный ответ. Один момент, который мне до сих пор не ясен - почему в ChildComponent не была вызвана функция setter? Я так понимаю, что Map изменился, я не видел этих изменений, потому что я отобразил другой массив (мне все еще нужно сделать этот массив, потому что в реальном проекте это немного сложнее). Но почему sett не был вызван? Просто из-за неподдерживаемого типа данных, который не позволяет обнаруживать изменения? - person WeekendMan; 05.01.2018