how to make a meteor template helper re-run/render after another template has rendered?

为君一笑 提交于 2019-11-29 15:11:31

问题


I have a template helper called {{renderNav}} in a template Nav

e.g.

Template.Nav.renderNav

and within that helper function I want to parse the rendered output of another helper within a different template

For example the helper

Template.contentWindow.content

which provides the html for

{{content}}

and my renderNav helper wants to part the html that replaces {{content}} to generate the html for

{{renderNav}}

how would I do this? right now the {{renderNav}} helper executes for or runs more quickly and so it is unable to parse the html that replaces {{content}}

@Hugo - I did the following in my code as you suggested

Template.contentWindow.rendered = function() {
    debugger;  
    return Session.set('entryRendered', true);
};

Template.Nav.renderNav = function() {
    debugger;
    var forceDependency;
    return forceDependency = Session.get('entryRendered');
};

When I run it, the debugger first stops when executing the renderNav helper. (Which makes sense with what I am seeing in terms of the race condition). Then contentWindow renders and I hit the breakpoint above the Session.set('entryRendered', true). But then the renderNav doesn't run again as you suggest it should. Did I misinterpret or incorrectly implement your suggestion?


回答1:


You need a dependency in the template that you want to rerun. There are few possibilities, depending on what data you want to get.

For example, you can set a reactive marker in the content template that will notify renderNav that it's done with drawing.

Template.contentWidnow.rendered = function() {
    ...

    // Set this on the very end of rendered callback.
    Session.set('contentWindowRenderMark', '' +
        new Date().getTime() +
        Math.floor(Math.random() * 1000000) );
}


Template.renderNav.contentData = function() {
    // You don't have to actually use the mark value,
    // but you need to obtain it so that the dependency
    // is registered for this helper.
    var mark = Session.get('contentWindowRenderMark');

    // Get the data you need and prepare for displaying
    ...
}

 


 

With further information you've provided, we can create such code:

content.js

Content = {};
Content._dep = new Deps.Dependency;

contentWindow.js

Template.contentWidnow.rendered = function() {
    Content.headers = this.findAll(':header');
    Content._dep.changed();
}

renderNav.js

Template.renderNav.contentData = function() {
    Content._dep.depend();
    // use Content.headers here
    ...
}



回答2:


If you want the navigation to be automatically rebuilt when contentWindow renders, as Hubert OG suggested, you can also use a cleaner, lower level way of invalidating contexts:

var navDep = new Deps.Dependency;

Template.contentWindow.rendered = function() {
    ...
    navDep.changed();
}

Template.renderNav.contentData = function() {
    navDep.depend();

    // Get the data you need and prepare for displaying
    ...
}

See http://docs.meteor.com/#deps for more info.

If, on the other hand, you want to render another template manually, you can call it as a function:

var html = Template.contentWindow();

The returned html will not be reactive. If you need reactivity, use:

var reactiveFragment = Meteor.render(Template.contentWindow);

See the screencasts at http://www.eventedmind.com/ on Spark and reactivity for details on how this works.

UPDATE

To add a rendered fragment to your DOM:

document.body.appendChild(Meteor.render(function () {
    return '<h1>hello</h1><b>hello world</b>';
}));

You can also access the rendered nodes directly using the DOM API:

console.log(reactiveFragment.childNodes[0]);


来源:https://stackoverflow.com/questions/17584522/how-to-make-a-meteor-template-helper-re-run-render-after-another-template-has-re

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!