-
Notifications
You must be signed in to change notification settings - Fork 27.4k
Partial $digest for scope subtree #5583
Comments
+1 |
This is already possible, I believe. However $scope.$apply() calls $rootScope.$digest(), which is probably the root of this issue. ... hmmm, $digest sets the phase of the root scope, but it starts looking at the async queue and watchers from the current scope and traverses down the hierarchy. So it's sort of a mix of supported and not. interesting :> |
This would need to be combined with a way to supress digest on the tree in general, or it would all too often be processed. I was thinking that a directive could cause the general digest loop to break out of a tree? eg: something like ng-sleep="true" This would allow sections of your application could be disabled, for performance. Maybe you could even trigger an update on them on demand? |
+1 |
+1 |
More on this subject from React library -- an elegant algorythm to perform diff only on the changed subtrees: http://calendar.perfplanet.com/2013/diff/ |
you can do this already by calling example: http://plnkr.co/edit/tV8kihZrm3hG3w7Fneq2?p=preview the issue is that most of entry points into Angular apps (event directives, etc) correctly call @kseamon has some tricks that temporarily rewrite scope hierarchy to reparent $rootScope with the current scope only. While clever, it's a nasty solution. Would it make sense to somehow target this only at isolate scopes and then provide a way for isolate scopes to overwrite what $rootScope in their context means, so that $rootScope for isolate scopes is still the main isolate scope of the component. This way components could opt-into partial digests. We'd still need to figure out how to propagate model updates from such component to the rest of the application in a sane way. |
The most annoying part of my $apply isolation hack is that when you want to trigger a dirty check higher up you need to use $timeout since you're already in a digest loop within your own scope so direct calls to $rootScope.$apply will not work. Also, it would be nice to have $applyLocal in addition to $digest to add on the $eval and try/catch functionality of $apply missing from $digest. |
$applyLocal will work only for calls that are explicitly local. We need a solution that will work for all directives used in this isolated context (e.g. ngClick). We could create something like a $localRootScope which if set, would be used by $apply instead of $rootScope. |
I didn't mean to suggest $applyLocal solves this issue–it would just be nice to have. Just to check, you're proposing that $localRootScope is a boolean that can be toggled at any time, or something that would be set by $new()? Also, to one of my earlier points, it would be very helpful if there was a way to "promote" a local digest (or an isolated one) to a full-page one without using $timeout (e.g. synchronously). At present, calling $rootScope.$digest/$apply from within the context of a local digest throws an exception. |
See this PR for a try: #8055 |
We are going to close this issue.
To summarize, this would be doable and some use cases would benefit, but the maintenance costs would be high (i.e. when problems need to be debugged), and there are already workarounds if you really know what you are doing :-) |
Could there be some documentation updates on these workarounds? With a note about the dangers/etc? |
I think it could be useful to have a possibility not to perform the overall $digest loop, but only on the specific scope subtree when some watchers are triggered. OFC optionally and on developer's own risk, when he does know exactly which scopes are affected by the change and which are not.
The text was updated successfully, but these errors were encountered: