简体   繁体   中英

Can't access public method in an object passed to an Angular component's @Input field

I've declared the following configurator object.

export class Config {
  constructor(public index: number, public junk: string[] = []) { }
  public count() : number { return this.junk.length; }
}

Then I pass it into my components input decorated field like this ( @Input() config : Config; ).

<div *ngFor="let thing of stuff; let config={index:index,junk:junk};">
  <app-thingy [data]="thing"
              [config]="config">
  </app-thingy>
</div>

When I access this.config (checking that it's been set in ngOnChanges() ) I see the values I'm setting but I can't access the method. I also noticed that any additional parameters I might have in the constructor or possible public fields in the class aren't seen neither. Basically, only the fields assigned explicitly in the HTML markup are available.

ngOnChanges(changes: SimpleChanges): void {
  if (changes.config) {
    //console.log((new Config()).count());
    console.log((this.config.count()));
  }
}

The commented out line will produce an error saying that there's no such a method on the object. The second line proves it wrong - there is such a method on the object. I also tried casting it using this.config as Config but that led to the same result.

I'm sensing that the object I'm passing from the HTML markup isn't at all typed Config and hence, it doesn't have any methods/variables I haven't assigned explicitly. Since I can't just go new Config(...) in the markup (as asked for and responded to), I'm not sure how I'm supped to make the stupid computer trust me that it's dealing with a nicely implemented class including its convenience method.

How should I deal with it?

The best approach to it I can imagine is to construct an internal Config object making a copy of the fields from the passed in object and then to bind the HTML interpolators to that instead. However, it seems soooo hacky that I'm certain it's either stupid or wrong (possibly both)...

I don't know what you are trying to achieve with let config={index:index,junk:junk}; in your code, and that would throw an error, at least when I just now tried it. When removing this line and properly declaring a new Config in your parent, your code should work.

Parent:

config = new Config(1,['one','two'])

Parent html:

<div *ngFor="let thing of stuff">
  <app-thingy [data]="thing" [config]="config"></app-thingy>
</div>

Child:

ngOnChanges(changes: SimpleChanges): void {
  if (changes.config) {
    //console.log((new Config()).count());
    console.log((this.config.count()));
  }
}

This seems to work just fine! DEMO: https://stackblitz.com/edit/angular-fnmk41?file=app%2Fapp.component.ts

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM