GithubHelp home page GithubHelp logo

Comments (8)

StorytellerCZ avatar StorytellerCZ commented on May 25, 2024

@jankapunkt @zodern thoughts?

from blaze.

jankapunkt avatar jankapunkt commented on May 25, 2024

I can take a look at it tonight

from blaze.

jankapunkt avatar jankapunkt commented on May 25, 2024

@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 onDestroyed callback?

from blaze.

michaelcbrook avatar michaelcbrook commented on May 25, 2024

@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 onDestroyed callback.

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.

Error: Can't select in removed DomRange
    at Blaze._DOMRange.DOMRange.$ (http://localhost:3000/packages/blaze.js?hash=981d8eb98840b94fa27e85bfc8334660676125f3:654:26)
    at Blaze.TemplateInstance.$ (http://localhost:3000/packages/blaze.js?hash=981d8eb98840b94fa27e85bfc8334660676125f3:3450:25)
    at Blaze.TemplateInstance.exampleOnDestroyed (/imports/ui/layouts/example/components/example.js:197:10)
    at http://localhost:3000/packages/blaze.js?hash=981d8eb98840b94fa27e85bfc8334660676125f3:3279:20
    at Function.Template._withTemplateInstanceFunc (http://localhost:3000/packages/blaze.js?hash=981d8eb98840b94fa27e85bfc8334660676125f3:3662:14)
    at fireCallbacks (http://localhost:3000/packages/blaze.js?hash=981d8eb98840b94fa27e85bfc8334660676125f3:3275:12)
    at Blaze.View.<anonymous> (http://localhost:3000/packages/blaze.js?hash=981d8eb98840b94fa27e85bfc8334660676125f3:3382:5)
    at fireCallbacks (http://localhost:3000/packages/blaze.js?hash=981d8eb98840b94fa27e85bfc8334660676125f3:1874:75)
    at Object.Tracker.nonreactive (http://localhost:3000/packages/tracker.js?hash=5ef67b97eaf2ca907dc38459283f2349bada6814:625:12)
    at http://localhost:3000/packages/blaze.js?hash=981d8eb98840b94fa27e85bfc8334660676125f3:1871:13 undefined

With some monkey patching though, I was able to get it to work by overriding Blaze.remove and just switching the destroy() and detach() calls myself:

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 onDestroyed is warranted because that seems to be the intended functionality and the way that it works everywhere else.

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.

https://github.com/veliovgroup/flow-router/blob/1b7a7364bd36736ea3583e499483ebab1bc46a98/client/renderer.js#L13-L24

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 Blaze.remove function not working correctly in the first place.

from blaze.

jankapunkt avatar jankapunkt commented on May 25, 2024

Well, that's a problem now. I just changed the order in #366 because this caused lots of DOMRange not attached errors. Now I think this issue is connected to all this. Do you already use the 2.6.1-rc.1 release? If not, please try it out if it fixes your issue.
Otherwise I think we have to make another round of debugging to find the source of the issue.

from blaze.

jankapunkt avatar jankapunkt commented on May 25, 2024

@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.

from blaze.

michaelcbrook avatar michaelcbrook commented on May 25, 2024

I just tried running 2.6.1-rc.1 just to check, and without the fix I posted, the problem still exists. I also tested the fix on 2.6.1-rc.1 and it worked correctly. So I'm in support of PR #374 still being pushed through.

from blaze.

jankapunkt avatar jankapunkt commented on May 25, 2024

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

from blaze.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.