Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Rename $postLink to $onLink or $onPostLink #14651

Closed
adamreisnz opened this issue May 23, 2016 · 8 comments
Closed

Rename $postLink to $onLink or $onPostLink #14651

adamreisnz opened this issue May 23, 2016 · 8 comments

Comments

@adamreisnz
Copy link

Given these component lifecycle hooks, find the odd one out:

$onInit()
$onChanges()
$onDestroy()
$postLink()

Why this discrepancy? Can we call the $postLink hook $onLink or $onPostLink to be consistent?

@Narretz
Copy link
Contributor

Narretz commented May 23, 2016

I assume it was done on purpose, but @petebacondarwin probably knows more.

@Narretz Narretz added this to the Ice Box milestone May 23, 2016
@petebacondarwin
Copy link
Contributor

petebacondarwin commented May 23, 2016

Significantly, there is no direct parallel for the $postLink hook in the Angular 2 hooks.
We added this hook as it felt like a point specifically in the Angular 1 lifecycle of a general directive (i.e. the post link function) that was not covered when using the mod.component() helper.

We felt that given its tight alignment with the post link function and that we wanted to make it clear that this did not match anything in Angular 2 it should have this name. To be honest we couldn't really come up with any real use cases for it but added it for completeness.

I am afraid that it would be a breaking change to rename this hook now so that is not going to happen.

Other than aesthetic is there any functional reason why this should change?

@adamreisnz
Copy link
Author

@petebacondarwin I've just started converting some Angular 1 directives to components, and I was also hoping to avoid having to use $postLink. However, the manual states:

$postLink() - Called after this controller's element and its children have been linked. Similar to the post-link function this hook can be used to set up DOM event handlers and do direct DOM manipulation.

And:

$onInit() - Called on each controller after all the controllers on an element have been constructed and had their bindings initialized (and before the pre & post linking functions for the directives on this element).

This lead me to assume that I should not have code like $element.on('keydown', keydownHandler); inside my $onInit, but rather in $postLink. That's the only reason I'm still using it.

However, if you're saying:

...we couldn't really come up with any real use cases for it but added it for completeness.

Does that mean it's safe to do DOM manipulation and bind DOM event handlers in the $onInit hook?

Other than aesthetic reasons, no, I have no functional reason for it to change. Was just curious why the discrepancy was there. If I can avoid using it and only have $onXxxxx handlers, that'd be great.

@adamreisnz
Copy link
Author

I've actually just moved all $element related logic from $postLink to $onInit and all my components still seem to be working fine. So I guess my assumption was wrong. Maybe the manual can be cleared up a bit on that point and indicate it's safe to bind event handlers etc. to the $element in $onInit as well?

@petebacondarwin
Copy link
Contributor

DOM manipulation should be in post link but adding handlers should be fine in $onInit.

But we felt that both of these things should be rare in components where the template is in charge of UI

@adamreisnz
Copy link
Author

One use case I have for having to access the element in the component code is moving CSS classes from the component element to the parent element of the actual component HTML. This is necessary now that replace: true is deprecated (see also #9837). So I pretty much have to do this on every component where I want to be able to apply additional modifier classes, e.g.:

this.classes = $element[0].className;
$element[0].className = '';

I guess I could refactor the keydown handler to use ng-keydown.

@gkalpak
Copy link
Member

gkalpak commented May 24, 2016

I think how safe it is depends on the template content. If it contains directives that manipulate the DOM in their linking functions, $postLink is the way to go (because it gets executed after child directives post-linking).
If you know the necessary element will be there, then it's safe to do it in the $onInit hook.

There might be another (theoretical) advantage of having DOM-related functionality in a dedicated method (such as $postLink): It might enable testing the controller in isolation from an actual DOM, which can speed things up.
But it still depends on specific usecase - e.g. it might not be possible to isolate all DOM-related logic inside one method, or you might eant to test it with a DOM anyway, etc - but it might be cleaner in some cases.

@Narretz
Copy link
Contributor

Narretz commented Apr 26, 2017

I think having the name different from the other lifecycle hook makes sense, based on the discussion here.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants