Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Angular 2.0 Lifecycle hook #5177

Closed
ghost opened this issue Nov 7, 2015 · 25 comments
Closed

Angular 2.0 Lifecycle hook #5177

ghost opened this issue Nov 7, 2015 · 25 comments

Comments

@ghost
Copy link

ghost commented Nov 7, 2015

Hi. I have a component for CRUD operations, in Update mode, the data is fetched using ajax after component is loaded, because of it I got this error when view is rendering:
TypeError: Cannot read property '...' of undefined in [null]
It's because my data is not initialized before view rendering/binding so it's null.
I used ng-if="ready" in the top of my component's markup and the ready flag is setting after fetching the data. It prevents view binding/rendering before data be ready, This solved the problem here. But I have a same problem in a nested component, so I'm wondered if is there a better way to solve this problem? I took a look at Lifecycle hooks, but there is no hook like OnBeforeBinding/OnBeforeRendering to help me with this issue.
Any suggestion?

@robwormald
Copy link
Contributor

When working with nested properties of objects that may not exist yet, you can do foo?.bar - this should work for you.

@ghost
Copy link
Author

ghost commented Nov 7, 2015

Thanks Rob. No it's not working not for nested object nor for the parent one. It seems angular 2.0 expects everything should be exist before rendering.

@robwormald
Copy link
Contributor

can you replicate this in a plunker please? helps to troubleshoot.

@ghost
Copy link
Author

ghost commented Nov 7, 2015

Well not familiar with plunker. So I published the sample in c9.io.
Here is its preview:
https://angular2-behzadeshan-1.c9users.io/src/index.html
If you launch debugger you will see page has 24 errors.
Here is the code:
https://ide.c9.io/behzadeshan/angular2

@pkozlowski-opensource
Copy link
Member

Well not familiar with plunker. So I published the sample in c9.io.

c9.io seems to require a sign-in which makes it no-go for reproducing issues.

Even if you are not familiar with plunker, you can open one from https://angular.io/docs/ (ex. https://angular.io/docs/ts/latest/api/core/NgModel-directive.html). Plunker is the same kind of tool like jsfiddle, codepen, jsbin etc. so if you are familiar with one of those tools you can use them as well.

@ghost
Copy link
Author

ghost commented Nov 7, 2015

Thanks Pawel for the Plunker example. I forked the example and changed it to demonstrate my problem.
http://plnkr.co/edit/eKxCBWdeYxDPfWf1cgix?p=preview
Steps:
1- Click Render view (6 errors will be occurred)
2- Click Load Data
3- Click Render view (0 errors will be occurred)
4- Click Erase data (6 errors will be occurred)
5- Click Render view (6 errors will be occurred)

@pkozlowski-opensource
Copy link
Member

@behzadeshan thnx for the plunk, it makes things more clear. 2 remarks to start with:

  • angular2 alpha.37 is like ... really ancient. We are on alpha.45 right now and there were toons of changes
  • @robwormald is right - you should be using elvis operator (member?.name) but once again, it needs newer version of ng2

@ghost
Copy link
Author

ghost commented Nov 7, 2015

FYI, in the code there is a propery named meber, You may suggest I should initiate it. But I can't, because I have this problem in my CrudBaseController, it's a base class that other crud controllers inherit it. So it even don't know what property it has to initiate it. In the other hand why I should initiate my properties in Update mode when there value will be passed again and it's means angular should render view twice. Once for initiating values and then for the real values. I think There is should be a flag like ready or a method like bind() to enable explicitly tell to angular to render view in such cases.

@ghost
Copy link
Author

ghost commented Nov 7, 2015

I am using the newest version alpha.45 in my production code, and has the same problem.

@pkozlowski-opensource
Copy link
Member

FYI, in the code there is a propery named meber, You may suggest I should initiate it

No, this is not what we are suggesting. The suggestion is to be explicit about what might be null and this is what the elvis operator is for: member?.name

@pkozlowski-opensource
Copy link
Member

Hmm, actually it won't work with ngModel as it would throw:

Parser Error: The '?.' operator cannot be used in the assignment at column 14 in [member?.name=$event] in App > div:nth-child(3) > input:nth-child(1)[[(ng-model)]=member?.name]

@todoubaba
Copy link
Contributor

@behzadeshan

    loadData(){
        this.member = { 
            name: "Behzad Eshan"
        };
    }
    render() {
        this.loadData();
        this.ready = true;
    }
    eraseData() {
        this.ready = false;
        this.member = null;
    }

@ghost
Copy link
Author

ghost commented Nov 7, 2015

@pkozlowski-opensource Even if it works, why I should change a lot of assignments in the markup when I can use a single flag or a single method in my code? Imagine in an enterprise project, most of developers will forget to use ? in their markup also this will force them to care about logic too and find which properties will be lazy loaded. It means UI designers should know about developers' code too.

@ghost
Copy link
Author

ghost commented Nov 7, 2015

@pkozlowski-opensource Elvis operator is working for disable directive, but look at my code [disabled]="entity?.subentity?.length > 0"
I had to use two? mark. It looks weird. If this is the only solution I prefer to use my own way by calling bind() method in the latest lazy loaded property and using ready flag in the top of my component's markup that will be set too true by bind method.

@pkozlowski-opensource
Copy link
Member

@behzadeshan I hear what you say about the elvis operator. Personally I'm still on a fence when it comes to its usage vs. what we know from ng1.

I'm going to leave this issue open so other can chime-in to express their opinion on Elvis vs. forgiving evaluation of expressions known from ng1.

@ghost
Copy link
Author

ghost commented Nov 7, 2015

@pkozlowski-opensource Thanks . I am not ok with ng1 forgiving evaluation either because of silent failures that it hides. I think there should be a third way to explicitly tell the angular that some properties are nullable, but not in the markup but in code (for example by annotation), because a property may be used in more than one place in markup, and if we want to mention it's nullablity by elvis operator in markup we should change more than one place. In the other hand mentioning a property nullablity in code will save view changes from code changes when setting or removing nullablity of the property.

@ghost
Copy link
Author

ghost commented Nov 7, 2015

@pkozlowski-opensource By the way will you support elvis oprator on ngModel as well?

@e-oz
Copy link

e-oz commented Nov 7, 2015

My first reaction to ?. was "why, we had it so simple in ng1", but then I tried to think about reasons: if expressions parser will not contain try-catch blocks, it can significantly improve performance, because try-catch often gives very negative impact. I don't know if it's real reason of existence of ?., but if my assumptions are correct, I'm ready to sacrifice few ? symbols for performance :)

@gionkunz
Copy link
Contributor

gionkunz commented Nov 8, 2015

@e-oz It's not only performance. It's also about being more explicit. It was very hard to debug issues with Angular 1 when an expression did not result in the expected output as the parser was so forgiving. In Angular 2 you'll get a detailed error why an expression can't be evaluated and you can explicitly tell Angular where to be forgiving.

@user414
Copy link

user414 commented Jan 5, 2016

@pkozlowski-opensource

So will NgModel support the elvis operator in the final release? Right now to address this type of issue that NgModel can't deal with the elvis operator I end up having to create a dummy object and copy all the field inside the object once they become available. It's not really elegant and was wondering if there's a better way to handle this?

@user414
Copy link

user414 commented Jan 6, 2016

We have the same problem as OP, it happens often in the case of a pre-filled form. Either we have to not use ngModel since the elvis operator doesn't work for now or use a dummy model. We chose to go with dummy model it ends up looking something like this

  • Create dummy model representing the data we are expecting from the backend and have all the field empty.
  • Render the all the view, in our view we have a loading screen
  • In the ngAfterViewInit we load our data from the backend, this is to make sure that when our call returns the view is fully rendered since we use the view annotation to hide our loading child component
  • Once the data is loaded copy the data inside our dummy object so that proper angular2 event can be generated to automatically update the view

This is not so elegant but only way found to use the ngModel. Otherwise you end up using {{model?.field}} which works to display the view but then have to take care of updating the model manually either via ngFormModel and control group or just simple document.getElementById none of which seems any better. I agree with OP that an extra lifecycle hook like OnBeforeBinding/OnBeforeRendering would seem to be an easy way to get out of this. If someone else found a way to address this would be interested to know as well.

@user414
Copy link

user414 commented Mar 12, 2016

As a follow up, after some refactoring the most elegant solution we came up with was to have some kind of json encapsulation service with an empty object that get filled in later with the http call. Somewhere along the betas this started to work.

@aciccarello
Copy link
Contributor

Is this about supporting the elvis operator in ng-model? If so maybe it should be renamed?

@vicb
Copy link
Contributor

vicb commented Sep 24, 2016

Please open a new issue with the most current pb

@vicb vicb closed this as completed Sep 24, 2016
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants