Angular 2 Pipes executing before ngOnInit
Asked Answered
M

1

8

I have a implemented a custom Pipe in Angular 2 RC5 which processes data that I get from the server. The problem I'm having is that the Pipe executes before the ngOnInit which is where I am making the calls to the server.

As a test I passed an-already populated list to the Pipe and everything works as expected. The only issue I'm having is that the Pipe executes when the page is rendered. And so the list in that case is empty.

Is there any way to "delay" the rendering of the page so that when the Pipe executes it has the data retrieved from the server?

This is a sample of my code:

Component

ngOnInit() {
    Observable.forkJoin([
        this.testService.get(),
        this.multilingualService.get(localStorage.getItem('currentPage'))
    ]).subscribe(servicesResult => {
        this.mainList = servicesResult[0];
        this.pageMultilinguals = servicesResult[1];
    },
    error => this.handleError(error));
}

Pipe

@Pipe({name: 'multiLang'})
export class MultilingualPipe implements PipeTransform {
    transform(value: string, pageMultilinguals: Multilingual[], context: number): string {

        for (let i = 0; i < pageMultilinguals.length; i++) {
            if (pageMultilinguals[i].reference === value && pageMultilinguals[i].contexTypeId === context) {
                return pageMultilinguals[i].value;
            }
        }
    }
}

Template

<span>{{ 'Test' | multiLang: pageMultilinguals: 9 }}</span>
Maul answered 6/9, 2016 at 15:35 Comment(2)
Can you add a check for empty data in your pipe and just simply return original value in that case?Thistledown
I just put a simple example in the template. This is for a multi lingual reference so you could have a reference 'Page_Header_1' and you get the value back.Maul
S
6

When Angular runs change detection the, then the pipe is executed the first time. After the first change detection run, ngOnInit() is called. Delaying the call to your pipe until ngOnInit() wouldn't help at all, because when you make the server call in ngOnInit() doesn't mean you get the response immediately. The HTTP request is an async call and the response comes eventually but ngOnInit() will be completed a long time already.

I think in your case it should be enough to just make the pipe safe for null values so it doesn't cause exceptions when the passed values are null:

@Pipe({name: 'multiLang'})
export class MultilingualPipe implements PipeTransform {
    transform(value: string, pageMultilinguals: Multilingual[], context: number): string {
        if(!value || !pageMultilinguals || !context) {
          return null;
        }
        for (let i = 0; i < pageMultilinguals.length; i++) {
            if (pageMultilinguals[i].reference === value && pageMultilinguals[i].contexTypeId === context) {
                return pageMultilinguals[i].value;
            }
        }
    }
}
Shutout answered 6/9, 2016 at 15:52 Comment(8)
Thanks for your answer. So just to clarify I can't really have a pipe that's "waiting" for data from the server if I need the data when the page loads. In my case I always need to have data so I guess might need to change my approach a bit.Maul
Just to elaborate a bit this is a small feature I was testing for me to have translatable terms. The pipe's job is simply for me to pass a reference and the text of the selected language is returned. I was trying to retrieve the "page terms" ngOnInit, but as you pointed out I can't have the pipe "delayed" and wait for data.Maul
I don't understand yet why this causes you troubles. A pipe is supposed to be called when Angular2 change detection detects changes (default) or every time change detection runs (for impure pipes), that's all there is.Delimitate
Yep you're right it worked, I'm sorry I thought that the Pipe is only run once and not whenever a change is detected. Thanks a lot, you've helped me understand Pipes a bit more :)Maul
@GünterZöchbauer I'm having issues with this... I will try solve it with more research. But if I can't, will post a question. My issue is thatmy @Pipe is applied to a JSON that changes as soon as data is received from an async call. So, I need it to apply when I receive the data (and therefore when the JSON has changed) and not before that...Servomechanical
@Servomechanical Sorry, I don't understand your explanation. Can you please create a new question with the code that demonstrates where and how you change your code and what the actual and expected result is?Delimitate
@GünterZöchbauer Of course, I will create right now. Thanks for your quick responseServomechanical
@GünterZöchbauer I have created the question. I will link it, but if you or OP owner request it, I can delete this comment even though it serves the purpose of learning about Angular2's @Pipe. #43181783Servomechanical

© 2022 - 2024 — McMap. All rights reserved.