Issue with binding and @ViewChild

醉酒当歌 提交于 2019-11-28 11:30:26

问题


This plnker is probably the quickest way to see the issue

I'm not sure if it's just some obvious gotcha when using ViewChild but it's very strange.

The plunker is showing 3 inputs:

  • The first input is a basic input and a button that can focus it.
  • The second input is bound to the same value, and clicking edit will unlock the input.
  • The third input is also bound to the same value, and clicking edit will unlock the input and give it focus.

However, when adding the ViewChild to get a reference to the input, the NgModel binding on the input stops working. But any other bindings you attach (like disabled) will still continue to function. If you comment out line 52 of app/extended.component it will bind again, but obviously now it can't focus.

The first input/button shows that this is apparently only an issue when you're binding to a property from the class you're extending.


In short, when I access the input via ViewChild my binding to NgModel breaks.

That is, given a base with property "someValue": Binds:

@Component({
  selector: 'binding-working',
  template: `<input type="text" [(ngModel)]="someValue" />`
})
export class Working extends Base<string> {  
  constructor() { }
};

Doesn't bind:

@Component({
  selector: 'binding-broken',
  template: `<input type="text" #imBroken [(ngModel)]="someValue" />`
})
export class Broken extends Base<string> {  
  @ViewChild('imBroken') input;
  constructor() { }
};

回答1:


Update 2.3.0

Great news!

According to angular blog http://angularjs.blogspot.ru/2016/12/angular-230-now-available.html

Developers can now take advantage of object inheritance for components. Share or simplify component functionality by inheriting from a parent component.

So then it should work without custom decorator => Plunker Example

More details you can see in this commit https://github.com/angular/angular/commit/f5c8e0989d85bc064f689fc3595207dfb29413f4

Old version

That's as designed.

Angular2 doesn't support the full inheritance (https://github.com/angular/angular/issues/7968#issuecomment-219865739).

Your child ViewChild decorator overrides propMetadata defined in the base Extended class. Hence your ExtendedInputBroken class doesn't have parent properties like baseLevel and baseLevelChange

Thierry Templier wrote a great article about class inheritance in Angular2

  • https://medium.com/@ttemplier/angular2-decorators-and-class-inheritance-905921dbd1b7#.8r5fuys6l

If you really want to do that i can offer you the following solution.

Just create custom decorator like this:

function InheritPropMetadata() {
  return (target: Function) => {
    const targetProps = Reflect.getMetadata('propMetadata', target);

    const parentTarget = Object.getPrototypeOf(target.prototype).constructor;
    const parentProps = Reflect.getMetadata('propMetadata', parentTarget);

    const mergedProps = Object.assign(targetProps, parentProps);

    Reflect.defineMetadata('propMetadata', mergedProps, target);
  };
};

And then apply it on your ExtendedInputBroken class:

@InheritPropMetadata()
export class ExtendedInputBroken extends Extended<string> implements OnInit {
  ...

Plunker demo

This link could interest you:

  • Extending component decorator with base class decorator


来源:https://stackoverflow.com/questions/38153962/issue-with-binding-and-viewchild

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!