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

Pr 14656 #14811

Closed
wants to merge 5 commits into from
Closed

Pr 14656 #14811

wants to merge 5 commits into from

Conversation

petebacondarwin
Copy link
Contributor

What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)

What is the current behavior? (You can also link to an open issue here)

What is the new behavior (if this is a feature change)?

Does this PR introduce a breaking change?

Please check if the PR fulfills these requirements

Other information:

@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request) and all commit authors, but as best as we can tell these commits were authored by someone else. If that's the case, please add them to this pull request and have them confirm that they're okay with these commits being contributed to Google. If we're mistaken and you did author these commits, just reply here to confirm.

1 similar comment
@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request) and all commit authors, but as best as we can tell these commits were authored by someone else. If that's the case, please add them to this pull request and have them confirm that they're okay with these commits being contributed to Google. If we're mistaken and you did author these commits, just reply here to confirm.

@@ -2499,6 +2538,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
$exceptionHandler(e);
}
}
if (isFunction(controllerInstance.$doCheck)) {
controllerScope.$watch(function() { controllerInstance.$doCheck(); });
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need to manually track the remove watch function because we are after the point when we might swap out the controller for another instance. This watch will naturally be removed when the controller scope is destroyed.

@gkalpak
Copy link
Member

gkalpak commented Jun 21, 2016

One thing to note:

In Angular 2, there is no "digest loop" (running until the values have stabilized, which means at least twice per digest cycle) and the change detection is "single pass". Since the change detection works differently in Angular 1, there can't be a 1-to-1 mapping of the behavior of DoCheck between the two.

In particular, the ng2 behavior could be mapped to two strategies in ng1:

  1. We run $doCheck() on every digest loop iteration (i.e. multiple times per digest cycle).
  2. We run $doCheck() as a post-digest task (i.e. once after the digest cycle is over).
    (This would be similar to how $onChanges() is implemented, btw.)

This PR uses strategy (1), so currently the order of execution when there is a change is: $doCheck --> $onChanges --> $doCheck. In ng2, it will be $onChanges --> $doCheck (see demo).
It is not 100% consistent, but it is as consistent as we can get (within reason).

What I am sceptical about, is that with the current ng1 implementation it will be possible to do changes that will be picked up in the current digest cycle and apps will work fine. In ng2, this won't be the case.
You will either get exceptions (in dev mode) or the UI won't reflect the changes initiated through ngDoCheck() (see other demo - comment enableProdMode(); in app/main.ts to change mode).

In that sense, it might be more consistent if we implemented strategy (2) without invoking another digest.

I am more like thinking load than proposing anything tbh...

@petebacondarwin
Copy link
Contributor Author

Although it is worth noting that in A2 it is not recommended to use both ngDoCheck and ngOnChanges together.

@gkalpak
Copy link
Member

gkalpak commented Jun 21, 2016

To be clear, my concern is not about $onChanges, it's about the view not being updated with changes initiated from ngDoCheck (in ng2).

@petebacondarwin
Copy link
Contributor Author

As an aside here are two demos of A2 ngDoChanges:

Date http://plnkr.co/edit/1d1rlm2efCP31MphBvsf?p=preview
Arrays http://plnkr.co/edit/ZssO7amzxBIg3WL5W1at?p=preview

@petebacondarwin
Copy link
Contributor Author

@gkalpak can you put a unit test (or demo) together to illustrate your concern in A1?

@petebacondarwin
Copy link
Contributor Author

petebacondarwin commented Jun 21, 2016

Oh, I just disabled Prod Mode and see what you now mean...

@petebacondarwin
Copy link
Contributor Author

But even if we put the changes in $$postDigest we will still have a problem right? SInce in dev mode it errors and in ng1 it would just do nothing (or wait till the next digest)

@mazzur
Copy link

mazzur commented Jun 21, 2016

@gkalpak as far as I understood the main constraint is that we should not be able to trigger changes outside the component in its doCheck hook (as it is in A2) while changes inside the component should work just as it's implemented in this request. Please correct me if I'm wrong.

@mazzur
Copy link

mazzur commented Jun 21, 2016

But even if we put the changes in $$postDigest we will still have a problem right? Since in dev mode it errors and in ng1 it would just do nothing (or wait till the next digest)

We can trigger digest on the component scope following the $doCheck call in $$postDigest so that only values from inside the component would be applied right away as it seems to be in A2.

@petebacondarwin
Copy link
Contributor Author

We can trigger digest on the component scope following the $doCheck call in $$postDigest so that only values from inside the component would be applied right away as it seems to be in A2.

Partial digesting is a worrying topic...

@petebacondarwin
Copy link
Contributor Author

@mazzur I think you are correct in your assumption that we should not trigger changes outside - but I don't think that we can honour this in Angular 1 without doing dastardly stuff, like partial digests

@@ -3872,6 +3872,51 @@ describe('$compile', function() {
]);
});
});

it('should work if $doCheck is provided in the constructor', function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test looks identical to the one I added above?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test above assigns the methods on the prototype. This test defines them on the instance from inside the constructor.
(Note that while both work in ng1, in ng2 only the prototype will work.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha okay, thanks for explaining :)

@petebacondarwin
Copy link
Contributor Author

So I think that we should go with this implementation but document the following divergences from Angular 2:

  • in Angular 2 you cannot define the ngDoCheck method inside the constructor, it must be on the prototype
  • in Angular 2 you must not use the ngDoCheck method to trigger a change outside of the component's template.
  • in Angular 1 you may get many more calls to $doCheck than you would to ngDoCheck in Angular 2 due to the differences in the change detection mechanism

@gkalpak
Copy link
Member

gkalpak commented Jun 21, 2016

Except that if we document the 1st deviation (not being on the prototype), we should document it for all lifecycle hooks.

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

Successfully merging this pull request may close these issues.

5 participants