Угловая двусторонняя привязка данных и отслеживание изменений в родительском компоненте - PullRequest
4 голосов
/ 15 мая 2019

Кажется, что нет способа наблюдать изменения в родительском компоненте при использовании двусторонней привязки данных.

У меня есть пользовательский компонент ввода для сбора списка тегов. Двухсторонняя привязка данных настроена и работает между этим компонентом и его родителем.

// the parent component is just a form
// here is how I'm adding the child component
<input-tags formControlName="skillField" [(tags)]='skillTags' (ngModelChange)="skillTagUpdate($event)"></input-tags>

В родительском компоненте, как вы смотрите связанную переменную на предмет изменений? Хотя это всегда актуально (я это подтвердил), я не могу найти никаких рекомендаций по реагированию на изменения.

Я пробовал:

ngOnChanges(changes: SimpleChanges) {
    if (changes['skillTags']) {
        console.log(this.skillTags);  // nothing
    }
}

и

skillTagUpdate(event){
    console.log(event); // nothing
}

Ответы [ 5 ]

3 голосов
/ 21 июня 2019

Когда вы реализуете собственное двустороннее связывание, вы должны реализовать Emitter событий.Синтаксис для этого является обязательным.

это означает, что у вас есть ловушка для прослушивания, если значение изменяется.

Вот демонстрационная версия:

<hello [(name)]="name" (nameChange)="doSomething()"></hello>
_name: string;
@Output() nameChange = new EventEmitter();

set name(val) {
  this._name = val;
  this.nameChange.emit(this._name);
}

@Input()
get name() {
  return this._name;
}

counter = 0;

ngOnInit() {
  setInterval(() => {
    this.name = this.name + ', ' + this.counter++;
  }, 1000);
}

Stackblitz

Из того, что я знаю, это кажется менее раздражающим способом его использованияи любое двустороннее связывание будет следовать одному и тому же правилу, независимо от того, что, то есть оно заканчивается словом Change!

0 голосов
/ 21 июня 2019

Ваша реализация на самом деле не является двусторонней привязкой данных, родительский и дочерний компоненты просто совместно используют ссылку на одну и ту же переменную skillTags.

Синтаксис [(tags)]='skillTags' является синтаксическим сахаром для [tags]='skillTags' (tagsChange)='skillTags = $event'

Вам необходимо реализовать tagsChange в дочернем компоненте следующим образом: @Output('tagsChange') tagsChange = new EventEmitter<any>();, затем в любое время, когда вы захотите изменить tags в дочернем компоненте, не делайте этого напрямую, но вместо этого используйте this.tagsChange.emit(newValue).

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

Теперь в родительском компоненте, если вы хотите сделать больше, чем skillTags = $event (неявно сделано с [(tags)]='skillTags'), просто добавьте другого слушателя с (tagsChange)='someFunction($event)'.

StackBlitz Demo

0 голосов
/ 18 июня 2019

1.Вы можете использовать вывод (Eventemitter)

2. Самым простым решением является rxjs / subject. это может быть наблюдателем и наблюдаемым одновременно

Использование:

1.Создать объект недвижимости в обслуживании:

import { Subject } from 'rxjs';

export class AuthService {
   loginAccures: Subject<boolean> = new Subject<boolean>();
}

2. Когда происходит событие при использовании дочерней страницы / компонента:

logout(){
  this.authService.loginAccures.next(false);
}

3.И подписаться на тему на родительской странице / компоненте:

constructor(private authService: AuthService) {
    this.authService.loginAccures.subscribe((isLoggedIn: boolean) => {this.isLoggedIn = isLoggedIn;})
}

Обновление

для двусторонней привязки вы можете использовать viewchild для доступа к элементам и свойствам дочерних компонентов

<input-tags #test></<input-tags>

и в файле ts

  @ViewChild('test') inputTagsComponent : InputTagsComponent;

save()
{
   var childModel = this.inputTagsComponent.Model;
}
0 голосов
/ 18 июня 2019

Не знаю, ищите ли вы это, но пытались ли вы использовать @Input ()?

В дочернем компоненте

@Input() set variableName(value: valueType) {
  console.log(value);
}

В родительском компоненте

<input-tags formControlName="skillField" [(tags)]='skillTags'
[valiableName]="skillTagUpdate($event)"></input-tags>

Функция ввода вызывается каждый раз, когда объект, связанный с функцией, изменяется.

0 голосов
/ 15 мая 2019

вы можете прослушать изменение:

<input-tags formControlName="skillField" [tags]='skillTags' (tagsChange)='skillTags=$event; skillTagUpdate();'></input-tags>

или использовать метод получения и установки:

get skillTags(): string {
    return ...
}
set skillTags(value) {
    variable = value;
}

другой подход:

 export class Test implements DoCheck {
  differ: KeyValueDiffer<string, any>;
  public skillTags: string[] = [];
  ngDoCheck() {
    const change = this.differ.diff(this.skillTags);
    if (change) {
      change.forEachChangedItem(item => {
        doSomething();
      });
    }
  }
  constructor(private differs: KeyValueDiffers) {
    this.differ = this.differs.find({}).create();
  }
}}
...