-
-
Notifications
You must be signed in to change notification settings - Fork 115
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
Blaze.remove() destroys DOM before calling onDestroyed() #372
Comments
@jankapunkt @zodern thoughts? |
I can take a look at it tonight |
@michaelcbrook I tested this with 2.6.1-rc and if I change the code to your suggestions the views will not be removed anymore from the DOM and remain drawn on the screen. Can you please give more context, why you need the view to remain attached to the DOM during |
@jankapunkt There are many times I use this, but one recent example I can give is when I initialized a jQuery plugin on a text input to let it autogrow when the text within it changes. The way the plugin works is it creates a hidden element at the end of the body mocking the current input, measures the width, and then updates the width of the original input to fit the content. To prevent memory leaks (from these hidden elements being added to the DOM), it requires that a destroy function is called when we don't care about it any longer. We call that in the Here's some actual code: import inputAutogrow from 'input-autogrow';
Template.example.onRendered(function exampleOnRendered() {
// initialize autogrow
this.$('input').inputAutogrow({ maxWidth: 800, minWidth: 220 });
});
Template.example.onDestroyed(function exampleOnDestroyed() {
// destroy autogrow
this.$('input').inputAutogrow("destroy");
}); This caused the following error to be thrown and the hidden element was not removed from the DOM.
With some monkey patching though, I was able to get it to work by overriding Blaze.remove = function (view) {
if (! (view && (view._domrange instanceof Blaze._DOMRange)))
throw new Error("Expected template rendered with Blaze.render");
while (view) {
if (! view.isDestroyed) {
var range = view._domrange;
range.destroy(); // THIS WAS ORIGINALLY AFTER THE IF STATEMENT BELOW (BUT NOT INSIDE IT)
if (range.attached && ! range.parentRange)
range.detach();
}
view = view._hasGeneratedParent && view.parentView;
}
}; I think keeping the DOM attached during Having said that, I tried several other solutions, like the one used inside flow-router-extra, but this created the same problem you mentioned of the DOM remaining drawn on the screen. const _BlazeRemove = function (view) {
try {
Blaze.remove(view);
} catch (_e) {
try {
Blaze._destroyView(view);
view._domrange.destroy();
} catch (__e) {
view._domrange.destroy();
}
}
}; But this did not work for me, and I wonder if this was written in response to the |
Well, that's a problem now. I just changed the order in #366 because this caused lots of |
@michaelcbrook please see #374 Actually your propsed solution works, what was problematic was that I also use flow-router-extra which made my drawing faulty but with a clean project this works. In turn I will have to make a PR to the router to fix this. |
I just tried running |
- 🧹 Codebase cleanup - 🔗 Related: meteor/blaze#372 - 🔗 Related: meteor/blaze#375 - 👷♂️ Removed unnecessary "monkey patching" around `Blaze.remove()`, thanks to @jankapunkt
__Major Changes:__ -⚠️ It is recommended to set `decodeQueryParamsOnce` to `true`, fixing #78, pr #92, thanks to @michaelcbrook -⚠️ By default use `{decodeQueryParamsOnce : true}` in tests -⚠️ Deprecated `staringatlights:inject-data`, in favor of `communitypackages:inject-data` -⚠️ Deprecated `staringatlights:fast-render`, in favor of `communitypackages:fast-render` __Changes:__ - 👷♂️ Merged #92, thanks to @michaelcbrook and @Pitchlyapp, fix #78 - 👨💻 Fix #93, thanks to @drone1 - 🤝 Support and compatibility with `communitypackages:inject-data` - 🤝 Support and compatibility with `communitypackages:fast-render` - 🤝 Compatibility with `[email protected]` __Other changes:__ - 📔 Overall documentation update and minor refinement - 👨🔬 Update test-suite to cover #93 - 🧹 Overall codebase cleanup - 👷♂️ Removed unnecessary "monkey patching" around `Blaze.remove()`, thanks to @jankapunkt - 🔗 Related: meteor/blaze#372 - 🔗 Related: meteor/blaze#375 __Dependencies:__ - 📦 `[email protected]`, *was `v6.5.2`*
I'm closing this as it's covered by release 2.6.1. Feel free to reopen when the issue persists in 2.6.1 |
Hi,
This problem only happens when you explicitly call
Blaze.remove(view)
, but this piece of code causes the DOM to be destroyed before calling theonDestroyed
callback.blaze/packages/blaze/view.js
Lines 695 to 697 in a8dab83
The way it should work (and how it works when a view is destroyed by any other means) is the DOM is destroyed after the
onDestroyed
callback is called.The solution, as far as I can tell, is to simply reverse the order of
range.detach()
andrange.destroy()
.In my testing, this fixes the problem.
Note that this problem only applies to explicit calls to
Blaze.remove(view)
. Destroying by other means all appears to work correctly.Related
This problem, however, also seems to appear in the
blaze-hot
package.blaze/packages/blaze-hot/update-templates.js
Lines 132 to 133 in a8dab83
This problem occurs when updating the JS code of a template. When a hot module reload is performed on the template, the
onDestroyed
callback is called, but if it tries to reference the DOM, it will throw an error.The solution is the same as the above, to switch the order of
detach()
anddestroy()
. When that is changed, the problem is fixed.Let me know if this is not the right place to post the issue about
blaze-hot
.Thank you!
The text was updated successfully, but these errors were encountered: