角度双向数据绑定和监视父组件中的更改

时间:2019-05-15 17:39:21

标签: angular eventemitter two-way-binding controlvalueaccessor

使用双向数据绑定时,似乎无法观察父组件中的更改。

我有一个用于收集标签列表的自定义输入组件。已建立双向数据绑定,并在此组件与其父组件之间进行工作。

// 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
}

更新:StackBlitz

5 个答案:

答案 0 :(得分:3)

实现自己的双向绑定时,必须实现事件发射器。语法是强制性的。

这意味着如果值更改,您将有一个钩子可以收听。

这是一个演示:

<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单词结尾!

答案 1 :(得分:0)

您可以收听更改:

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

或使用getter和setter:

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();
  }
}}

答案 2 :(得分:0)

1。您可以使用output(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;
}

答案 3 :(得分:0)

不知道这是您要找的内容,但是您是否尝试过使用@Input()?

在子组件中

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

在父组件中

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

每次更改绑定到该函数的对象时,都会调用输入函数。

答案 4 :(得分:0)

您的实现实际上不是双向数据绑定,父组件和子组件只是共享对同一skillTags变量的引用。

语法[(tags)]='skillTags'[tags]='skillTags' (tagsChange)='skillTags = $event'的语法糖

您需要在子组件中实现tagsChange,如下所示:@Output('tagsChange') tagsChange = new EventEmitter<any>();,然后任何时候要将tags修改为子组件,都不要直接执行,而是使用{ {1}}。

这时,您将具有真正的双向数据绑定,并且父组件是变量的唯一所有者(负责对变量应用更改并将更改传播给子代)。

现在,在父组件中,如果您想做的事情不只是this.tagsChange.emit(newValue)(暗中用skillTags = $event完成),那么只需用[(tags)]='skillTags'添加另一个侦听器即可。

StackBlitz Demo