22

Using Angular 2+, how can I do something like bellow in the HTML?

{{ object.array.map( (o)=> o.property ) }}

This code crashes the angular application. I have to use Pipe or something like that?

3
  • Make a function for that in your typescript code and call that function instead? Not sure if that's exactly what you're trying to do though Commented Jul 18, 2019 at 18:57
  • Im just trying to do the 'Array.map' function in the HTML. Commented Jul 18, 2019 at 18:59
  • You can't. Do it when your object.array arrives in the component. Commented Jul 18, 2019 at 19:08

4 Answers 4

25

You can't define functions in Angular expressions. So you have to use pipes instead which are optimized for the templates. They are reusable across other components.

<pre>{{ object.array | pluck:"property" | json }}</pre>

With a pluck pipe:

@Pipe({name: 'pluck'})
export class PluckPipe implements PipeTransform {
  transform (input: any[], key: string): any {
      return input.map(value => value[key]);
  }
}

It's not recommended to call functions on the component to calculate values for the template. This moves work from the component to the template, and if you need data to be mutated then do that work in ngOnInit() or in ngOnChanges() instead.

Pipes have purity which means they are executed only when the inbound data is mutated. When you call a function like {{doWork(object.array)}} then Angular does not know if the function doWork() is pure or not. So it assumes it is not pure and calls it for each change detection.

Updated:

Anytime you work with Arrays in Angular you should be treating them as immutable. Where you create a new instance of that Array when you need to modify it. For example; items = [...items, newItem]; instead of items.push(newItems).

This resolves change detection problems related to pipes, ngFor, OnPush change detection and state stores.

https://medium.com/dailyjs/the-state-of-immutability-169d2cd11310

Sign up to request clarification or add additional context in comments.

5 Comments

yes, but making this pipe "pure" means that you must change the array reference everytime a member is changed in order to accurately reflect the model. methods like push and splice can't be used safely, nor can mutating an item in the array. This is non transparent and could lead to weird or hard to understand bugs.
non transparent immutability is absolutely a source of bugs.
@bryan60 anyway, I understand what you're saying. I just don't think it's related to the OPs question. It's a longer discussion.
perhaps it is, but your answer to OP's question should mention that this carries a dependency (or shortcoming) on treating your array as immutable if using this pipe, as it may be non obvious.
@bryan60 answer has been updated. Thank you for your feedback. Sorry for being prickly about it.
6

you could find some work around's to make this work, but my answer is you shouldn't do this as function calls in template negatively impact performance, as do impure pipes which this would require to be reliable.

Consider instead:

mappedArray = [];

ngOnInit() {
  this.mappedArray = object.array.map( (o)=> o.property );
}

{{ mappedArray }}

clean, reliable, easy to read / modify and easy to understand. Also gives more fine tuned control over when your functions evaluate.

3 Comments

💯 this consider the best solution in this case 👍
What if the content of object.array is modified later?
@ConnorsFan then it is important to ensure in your controller that the map function is re run in those cases. The point is to have fine control over when this occurs as to not become a performance drag and for the component to operate in a clear and transparent manner.
3

you can just create a get property and use it like this

component

   data = [
     {property : 'a'},
     {property : 'b'},
     {property : 'c'},
     ]

  get properties () {
    return this.data.map( (o)=> o.property )
  }

template

{{properties | json}} 

demo🔥🔥

1 Comment

Thanks - best answer imo. Quick and easy to implement and it works
1

In your component, you can have a function:

someFunction(arr: any[]){
    return arr.map(o => o.property);
}

And in your html template, assuming arr is some defined array already, you can simply just call that function where you want the array to be used. Example:

<div *ngFor="let object of someFunction(arr)>
    {{object.property}}
</div>

Unfortunately, there is no way to directly invoke code like that directly in the html template without some use of functions.

*it is also worth noting this code is not very optimized because someFunction() will be repeatedly getting called over and over again due to where it exists in the template.

1 Comment

you canot invoke array.map() directly in html using Angular

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.