如何获取(当前模板的)父模板实例

时间:2015-01-14 17:56:59

标签: meteor meteor-blaze

有没有一种干净的方法来获取当前模板的父模板? Meteor的API中没有正式记录的内容。 我说的是Blaze.TemplateInstance,而不是上下文(即不是Template.parentData)。

5 个答案:

答案 0 :(得分:28)

最后,我使用Meteor' parentData扩展了模板实例,如下所示:

/**
 * Get the parent template instance
 * @param {Number} [levels] How many levels to go up. Default is 1
 * @returns {Blaze.TemplateInstance}
 */

Blaze.TemplateInstance.prototype.parentTemplate = function (levels) {
    var view = this.view;
    if (typeof levels === "undefined") {
        levels = 1;
    }
    while (view) {
        if (view.name.substring(0, 9) === "Template." && !(levels--)) {
            return view.templateInstance();
        }
        view = view.parentView;
    }
};

示例用法:someTemplate.parentTemplate()获取直接父级

答案 1 :(得分:11)

  

是否有一种干净的方式来获取当前的父模板   模板?

目前,我不知道,但这应该在未来某个时间发生,作为计划的“更好的API来设计可重用组件”的一部分(这在Meteor post 1.0 roadmap中讨论)。

目前,这是我在项目中使用的解决方法:

// extend Blaze.View prototype to mimick jQuery's closest for views
_.extend(Blaze.View.prototype,{
    closest:function(viewName){
        var view=this;
        while(view){
            if(view.name=="Template."+viewName){
                return view;
            }
            view=view.parentView;
        }
        return null;
    }
});

// extend Blaze.TemplateInstance to expose added Blaze.View functionalities
_.extend(Blaze.TemplateInstance.prototype,{
    closestInstance:function(viewName){
        var view=this.view.closest(viewName);
        return view?view.templateInstance():null;
    }
});

请注意,这仅支持命名的父模板,并且应该以与jQuery closest相同的方式工作,以将父视图节点从子节点遍历到最顶层的模板(正文),搜索相应的命名模板。

一旦Blaze的扩展程序已在您的客户端代码中的某处注册,您就可以执行以下操作:

HTML

<template name="parent">
  <div style="background-color:{{backgroundColor}};">
    {{> child}}
  </div>
</template>

<template name="child">
  <button type="button">Click me to change parent color !</button>
</template>

JS

Template.parent.created=function(){
  this.backgroundColor=new ReactiveVar("green");
};

Template.parent.helpers({
  backgroundColor:function(){
    return Template.instance().backgroundColor.get();
  }
});

Template.child.events({
  "click button":function(event,template){
    var parent=template.closestInstance("parent");
    var backgroundColor=parent.backgroundColor.get();
    switch(backgroundColor){
      case "green":
        parent.backgroundColor.set("red");
        break;
      case "red":
        parent.backgroundColor.set("green");
        break;
    }
  }
});

答案 2 :(得分:9)

到目前为止我一直在做的是,如果我需要在子模板的函数中访问父实例,我会尝试重构此函数以在模板上声明它,并且然后将它作为参数传递给孩子,然后孩子可以执行它。

作为一个例子,假设我想在子模板中增加父模板上的模板变量。我可以这样写:

Template.parentTemplate.onCreated(function () {
  var parentInstance = this;
  parentInstance.count = new ReactiveVar(1);
});

Template.parentTemplate.helpers({
  incrementHandler: function () {
    var parentInstance = Template.instance();
    var count = parentInstance.count.get();

    return function () {
      var newCount = count + 1;
      parentInstance.count.set(newCount);
    };
  }
});

然后包括我的孩子模板:

{{> childTemplate handler=loadMoreHandler}}

设置我的活动:

Template.childTemplate.events({
  'click .increment-button': function (event, childInstance) {
    event.preventDefault();
    childInstance.data.handler();
  }
});

答案 3 :(得分:2)

如果您不想扩展Blaze.TemplateInstance,可以像这样访问父实例:

Template.exampleTemplate.onRendered(function () {
  const instance = this;
  const parentInstance = instance.view.parentView.templateInstance();
});

仅在Meteor 1.4.x中测试

答案 4 :(得分:0)

您可以使用Aldeed's template-extension

等软件包

可以使用以下方法:

templateInstance.parent(numLevels, includeBlockHelpers)