6

Let's say that somewhere in my template I'm using:

<div *ng-for="#fooItem of foo">
    {{fooItem.bar.baz.value}}
</div>

I would like to be able to write something like {{theBaz}} instead of using fooItem.bar.baz every time in my loop. Is there a way to achieve that? Maybe some syntax that allows to define arbitrary variables?

The documentation mentions usages that involve components/directives setting the value, but apparently nothing simpler.

1

1 Answer 1

3

One possible solution would be with a small Angular2 Pipe.

get-the-baz.ts:

import {Pipe} from 'angular2/angular2';

@Pipe({
    name: 'theBaz'
})

export class GetTheBaz {
    transform(item) {
        return item.bar.baz.value
    }
}

And in your app:

import {Component, bootstrap, NgFor} from 'angular2/angular2';
import {GetTheBaz} from './get-the-baz';

@Component({
    selector: 'my-app',
    directives: [NgFor],
    pipes: [GetTheBaz],
    template: `QuickApp: 
    <div *ng-for="#item of list">
        {{item|theBaz}}
    </div>
    `
})

Depending on your use case, this may or may not be a good idea.

EDIT: Two more solutions

Check out the code below I have added:

  1. piping on the list and,
  2. a good ol'fashioned function

(I also included the above pipe on an item solution for comparison)

import {Component, bootstrap, NgFor} from 'angular2/angular2';
import {Pipe} from 'angular2/angular2';

// This may not be the most efficient way, I'll do some research and edit in a moment
var _getC = val => (val && val['a'] && val.a['b'] ) ? val.a.b['c'] : null; 


@Pipe({
    name: 'pipeC'
})
export class pipeC {
    transform(val) {
        return _getC(val)
    }
}

@Pipe({
    name: 'pipeCFromList'
})
export class pipeCFromList {
    transform(list) {
        return list.map(_getC);
    }
}

@Component({
    selector: 'my-app',
    directives: [NgFor],
    pipes: [pipeC, pipeCFromList],
    template: `QuickApp:
    <p>pipe item:</p> 
    <div *ng-for="#item of list">
        <item [text-content]="item|pipeC"> </item>
    </div>

    <p>pipe list:</p>
    <div *ng-for="#num of list|pipeCFromList">
        <item [text-content]="num"> </item>
</div>
    <p>func item:</p>
    <div *ng-for="#item of list">
        <item [text-content]="getC(item)"> </item>
</div>
    `
})

class AppComponent {
    public getC (val) {
        return _getC(val);
    };
    list = [{a:{b:{c:1}}}]
}
bootstrap(AppComponent);

Try these on for size as well^

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

2 Comments

Thanks. Cool solution. Leaving it open in case someone suggests something better. I think a hidden input field would also work but that's not really pretty.
I definately get your hesitation, its not great. I guess ultimately you are going to have to put your propertly access logic somewhere. If you could of done destructured assignment in the ng-for that would of been another option. You may infact find just putting it all out there to see might be the best option. Or of course a good old fashioned rethink. Either way, g'luck

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.