-
Notifications
You must be signed in to change notification settings - Fork 27.5k
Support detaching/re-attaching scope #5301
Comments
+1 for this feature as we ran across an optimization issue while developing a tab system with Angular. Each tab had a template inside it with multiple watchers. We didn't want the user to lose their work (e.g. their form inputs and UI states like scroll position), so we just hid the templates, but this lead to the application to slow down on each digest. Our templates should unbind from the scope while they are hidden and rebind when back in view. Right now there's a few optimization workarounds this lack of feature: |
+1 for this feature as I'm facing same issue while creating dashboard widgets where I don't want the user to lose their work when close/add pods in dashboard. I'm using jqLite .detach() method so that I can add pods once again in DOM without losing any data but pods pick another scope due to which handlers, watchers not worked. |
Take a look at https://github.com/shahata/angular-viewport-watch - it basically disables and enables watchers automatically as they get scrolled out of viewport and back in (perf for long |
I've decided to fork and modify Angular to add a flag that allows the digest loop to skip a $scope's children. I wrote up my motivation and the details of watcher pausing here. Appreciate any feedback on this optimization strategy. |
+1. I've build a routing/navigation system on top of Angular, in witch it is mantained a stack of "opened activity" that the user is working with, but the opened activity that are not in the top of the stack are "paused", i'd like not to loose the user temporary data on "paused" activity (very much like Android systems) but also not to slow down the app when the stack of acrtivity grows.. so this issue is very very Important to me. |
Although this is a significant pain point for certain kinds of applications built with Angular 1, it is not a straightforward thing to fix without creating many many opportunities for subtle bugs. Perhaps one could make use of ngUpgrade to allow those parts of the app that need to be suspended to be controlled by Angular 2? |
+1 Surely if this guy can do it, the Angular team could. I can't really think of an app with multiple "views" that wouldn't benefit from this feature. Please please please put it into 1.x branch. @petebacondarwin ngUpgrade to a framework that isn't even out of release candidate? Most of the Angular developers I know are moving/moved to React because of this kind of treatment. |
@poshest for sure it is easy to toggle watching for a childscope. The trouble is that there are subtle issues that can occur if you do not carefully control the boundary between the suspended scope and the rest of the scope hierarchy. In Angular 1 there a many paths that can lead to a value being made available across a scope boundary, such as use of We have spent a lot of time thinking about this over the years and this is in fact one of the driving forces behind the big rewrite that is Angular 2. In Angular 2 there is much more control over the movement of data between components and so it is much safer to select parts of the component tree which do not need to run dirty checking. If we implemented one of the many suggested solutions to this problem we would then be faced with maintaining it, and more importantly supporting the complicated corner cases that are really hard to control. But more importantly, application developers might find that their apps are not updating as they expect and it will not necessarily be obvious or easy to identify the cause. There are already a number of production applications running on Angular 2 in the wild. My impression from those projects is that they enjoy the improved ergonomics of the new version of Angular. Of course each project must make a choice about what level of risk it is willing to take on and the timelines of the application that is being developed. |
@petebacondarwin thank you. A very sound response. I do see the motivations behind pushing people to Angular 2 and iceboxing most requests for 1.x functionality (although why not just close them if you're not going to build them). I started building in Angular 1.x a couple of years ago precisely because I felt it was suitable for non-trivial apps. I'm still getting over my disappointment that it simply is not and in that short time has become legacy. It's like buying a car that you didn't know was limited to 30mph, and being told that the only fix is buy the new faster model. My major concern with your recommendation to upgrade is that I have no guarantee that Angular 2 will fix this issue. To that end, perhaps you can help me understand what Angular 2 does that will help in this precise situation? Will it just create less watches so you can ng-hide more? Or will it have some smart disabling of watches when they're hidden? The use case, as explained above, is lots of heavy functionality (ng-repeats, ng-ifs/shows etc, and deeply nested components) for each tab, and wanting not to have to re-render those every time the tab is re-visited. I am already using 100% 1.5 components and one-way bindings. |
Someone will do better than I will. But here's the short of it. Angular 2 (A2) addresses the digest churn problem in two ways
We can trigger a new round of change detection for that component whenever we want by calling I think that's the on-demand refresh option that you want. It's not precisely a disable/enable switch. It's more a switch for taking over when change detection happens for a particular component and its sub-tree. Read about it in this post from Pascal Precht of ThoughtRam (an oldie but goodie). This facility is baked into A2. Just one of many reasons to like Angular 2. |
@wardbell thanks for your response and the link. The digest churn isn't the problem I'm trying to address here, although removing the second and later passes will obviously help. I have two problems. (a) It takes a long time to render my complex components. This is the root cause and this is not addressed by this thread. To mitigate this somewhat I wish to at least not render those complex components more than once. But... (b) If I render a component and then keep it around (hidden by ng-hide), it will continue to be dirty checked in the background. Because of the complexity of my app, I might have 1000s of watches hidden behind the ng-hide. Halving (or better) the digest cycle time is great, but it doesn't solve the problem. In addition, in response to your point 1 "w/o the developer having to do anything"... as I understand it, in Angular 2 the developer has to do lots - ie change the entire app to use the "data flows down, functions flow up" pattern. This is a fundamental change that involves potentially a lot of work for the developer, and is the exact reason why Angular is able to give the one-pass guarantee. It's like me saying "my framework is really fast, because loops aren't allowed - if you create a loop, the framework will throw an error". Two-way data binding was what MADE Angular 1.x popular. Your point 2. is much closer what I am after. The article you referenced seems complicated and I'll have to read it a few more times. Once again I'm disappointed that I need to understand so much about the Angular internals to make it work. But I'm still left yearning for a very simple
This is a lovely experience for the developer. markForCheck is nice for those fine-grained control requirements, but requires too much finessing for this very common use case. BTW, you can currently do 1 and 2 with this, which is everywhere in my code.
"Oh, ng-ifshowwatch... |
@poshest here is another article - https://www.lucidchart.com/techblog/2016/05/04/angular-2-best-practices-change-detector-performance/ - but be aware that the API has changed since this was written. In it the author writes:
As you say this does require the developer to use immutable data structures and one way data-flow if you don't want to do any change detection yourself. But I think the key for your goal is that in Angular 2 we have full control over the change detection strategy for each component. For example one can use https://angular.io/docs/ts/latest/api/core/index/ChangeDetectorRef-class.html |
@vahan-hartooni FYI the broken link on your post. It's really helpful, so pls update. :) |
@petebacondarwin do you have any feedback on @vahan-hartooni 's approach to this? It's my favourite way to achieve this much needed feature. It's a couple of lines of code, and Vahoon has already determined that it passed all the AngularJS tests. Worst case, it doesn't work in some of those "subtle" cases you mention, but if you create the new flag as |
I've added it to the 1.5.x milestone so that we can consider it further. |
Wonderful! Thank you @petebacondarwin :) |
Hi, It would be really nice to have an implementation of a I wrote a module that imitates Angular 2's behaviour but it would be really nice and cleaner to have a similar implementation integrated in Angular 1.5 or Angular 1.6. https://github.com/wishtack/ng-steroids If you agree with the behaviour, I would be glad to get some feedback before making a pull request. Thanks! |
Is there any chance of something happening on |
The feature set for 1.6.0 is more or less fixed, so I don't see it as likely. |
@petebacondarwin not sure how people should read your final two comments? Are the team planning to implement this ('we have agree to implement...'), or are you looking for outside contribution? If @shahata's PR was modified to have a more Angular Change Detection feel, would that be merged? |
Hi Tim |
@petebacondarwin we have very few resources to migrate to Angular 2 right now. My only option is getting max juice out of ol' AngularJS. Can I suggest that, in the meantime, the @vahan-hartooni suggestion is implemented. Sure, it's not consistent with Angular 2, but it's non-breaking as you said, and would allow us to switch off and on parts of the digest tree for some big big performance gains. |
Sorry for ignoring all the refs to the chosen @shahata solution. I see that it's pretty similar to @vahan-hartooni's code, but with nice For starters, what does testing even involve? Just running the existing automated tests? Or do I need to write some new tests to properly address @igalfaso in #10658 who says "this needs to be done in a way that does not involve a lot of work for developers to upgrade to these new features, nor break common patterns used today". I'm not even remotely equipped to do that. |
No problem. Perhaps we can put together a new PR and you can try it out for us? |
Absolutely happy to do that :)
|
@petebacondarwin any progress on that PR? :) |
No movement yet. Sorry. I'll find some time this week. |
Thanks Pete! I appreciate it. :)
|
This can be very helpful for external modules that help making the digest loop faster by ignoring some of the watchers under some circumstance. Example: https://github.com/shahata/angular-viewport-watch Thanks to @shahata for the original implementation. Closes angular#5301
Great! Absolutely, will do. :)
|
This can be very helpful for external modules that help making the digest loop faster by ignoring some of the watchers under some circumstance. Example: https://github.com/shahata/angular-viewport-watch Thanks to @shahata for the original implementation. Closes angular#5301
This can be very helpful for external modules that help making the digest loop faster by ignoring some of the watchers under some circumstance. Example: https://github.com/shahata/angular-viewport-watch Thanks to @shahata for the original implementation. Closes angular#5301
This can be very helpful for external modules that help making the digest loop faster by ignoring some of the watchers under some circumstance. Example: https://github.com/shahata/angular-viewport-watch Thanks to @shahata for the original implementation. Closes angular#5301
This can be very helpful for external modules that help making the digest loop faster by ignoring some of the watchers under some circumstance. Example: https://github.com/shahata/angular-viewport-watch Thanks to @shahata for the original implementation. Closes angular#5301
This can be very helpful for external modules that help making the digest loop faster by ignoring some of the watchers under some circumstance. Example: https://github.com/shahata/angular-viewport-watch Thanks to @shahata for the original implementation. Closes angular#5301
This can be very helpful for external modules that help making the digest loop faster by ignoring some of the watchers under some circumstance. Example: https://github.com/shahata/angular-viewport-watch Thanks to @shahata for the original implementation. Closes angular#5301
This can be very helpful for external modules that help making the digest loop faster by ignoring some of the watchers under some circumstance. Example: https://github.com/shahata/angular-viewport-watch Thanks to @shahata for the original implementation. Closes angular#5301
This can be very helpful for external modules that help making the digest loop faster by ignoring some of the watchers under some circumstance. Example: https://github.com/shahata/angular-viewport-watch Thanks to @shahata for the original implementation. Closes #5301 Closes #16308
This is basically, a reversible
$destroy
for scopes.Detaching the scope would mean:
I could see this being used for optimizations such as not running watchers on hidden DOM (that could be detached).
I think a factor that affects the adoption of Angular is the fact that having many watchers could slow down the application. Currently, there's no way to "pause" the watchers on DOM that's not currently visible.
It's possible to hack out a directive to do this, but I'm wondering if this feature is of value to the rest of the Angular community as part of the Angular core.
I noticed that jqLite doesn't have
.detach
..remove
actually destroys the scope of the element so after re-adding it to the DOM, it actually picks up the another scope and has already lost its own scope.The text was updated successfully, but these errors were encountered: