How to access getter/setter accessors from angular 4 in template binding?

老子叫甜甜 提交于 2020-02-21 13:46:51

问题


Lets say I have the following getter/setter methods

get next() {
  console.log(this.people[this._index], this._index);
  return this.people[this._index];
}

set next(i: any) {
  this._index = (+i) + 1;
  this._index = (+i) % this.people.length;
}

and I want to call this in the following way:

<ng-template ngFor let-person="$implicit" [ngForOf]="people" let-i=index let-last=last>
  <app-card [cardItem]="people[i]" [nextCard]="next(i)"></app-card>
</ng-template>

PS: Think of this as circular array. Where by I need prev, current, and next items.

However I get the following Error

Angular: Member 'next' in not callable

Why is that? And whats the solution?

Thanks

Edit

Thank you guys for your help and explanation. With your help i managed to make it work:

<app-card [currentCard]="people[i]" [nextCard]="people[i === people.length - 1 ? 0: i + 1]" [prevCard]="i == 0 ? people[people.length - 1] : people[i - 1]"></app-card>

So its pretty much circular array. Lets assume we have the following:

people["James Dan", "Aluan Haddad", "Jota Toledo"]

So few conditions:

  1. If I stand in the beginning of the array (i.e. index = 0) - then my prev will be people[people.length - 1] which is the last element in the array. And if my current is on index 1, then my prev will be index 0 and next will be index 2.

回答1:


The Angular template syntax is, in general, a subset of JavaScript syntax with some notable differences and with many restrictions.

However what you have here is actually invalid in JavaScript as well. It is not valid to call a property accessor. Ever.

Given the following property

get p() {
  console.info('read p');
  return this.wrapped;
}
set p(value) {
  console.info('wrote p');
  this.wrapped = value;
}

The get accessor is invoked implicitly when the property thusly named is read.

For example:

console.log(o.p); // read p

The set accessor is invoked implicitly when the property thusly named is written.

For example:

o.p = x; // wrote p;

The same rules apply in Angular templates.

However, your example of

<app-card [cardItem]="people[i]" [nextCard]="next(i)">

suggests that a property is not what you want here.

The correct usage of a property implies the following syntax

<app-card [cardItem]="people[i]" [nextCard]="next = i">

Which I do not believe is supported by the Angular template syntax and even if it is doesn't make a lot of sense and would be hard to read.

Instead you should create a method that returns a value

getNext(i: number) {
  this._index = i + 1;
  this._index = i % this.people.length;
  return this.people[this._index];
}

Then used in your template as

<app-card [cardItem]="people[i]" [nextCard]="getNext(i)">

Having said that, I think the entire design is questionable. You seem to be going through contortions to store excess mutable state independently of the array that naturally maintains it.

I believe you would be much better served by removing the method and the property entirely and using

<app-card
  *ngFor="let person of people; let i = index"
  [previousCard]="people[i === 0 ? people.length - 1 : i - 1]" 
  [cardItem]="person"
  [nextCard]="people[i === people.length - 1 ? 0 : i + 1]">

If you want a cleaner syntax, you might define a property, with a get accessor only, that returns a view of your array as objects with previous, current, and next properties.

get peopleAsPreviousCurrentAndNextTriplets() {
  return this.people.map((person, i) => ({
    previous: this.people[i === 0 ? this.people.length - 1 : i - 1],
    current: person,
    next: this.people[i === this.people.length - 1 ? 0 : i + 1]
  }));
}

This can be more readable in complex code because its abstracts away the index for more semantic properties that we can use directly. Perhaps more importantly, it enables TypeScript's world-class tooling to validate the computation.

<app-card
  *ngFor="let item of peopleAsPreviousCurrentAndNextTriplets"
  [previousCard]="item.previous" 
  [cardItem]="item.current"
  [nextCard]="item.next">

And thus we come full circle. Note how we define the get accessor and how we read the property it defines without (), implicitly invoking that accessor.

The last example is probably overkill for this scenario but I think it's useful nonetheless.



来源:https://stackoverflow.com/questions/45648714/how-to-access-getter-setter-accessors-from-angular-4-in-template-binding

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