【问题标题】:Passing in a Handlebars template as a variable to a Handlebars template将 Handlebars 模板作为变量传递给 Handlebars 模板
【发布时间】:2014-03-24 07:33:56
【问题描述】:

我有一种情况需要渲染用户创建的 Handlebars 模板。我已经能够拼凑出一个解决方案:使用视图将用户生成的模板 + 上下文编译成 HTML,然后使生成的字符串可用于“最终”模板。

我希望能够将模板作为变量公开给“最终”模板,并让最终模板评估它,就好像它是实际的 HBS 代码一样;但如果我使用三重大括号{{{,则车把变量(当然)会被转义。

还有其他方法可以做到这一点吗?也许是一个助手,它首先用一些上下文编译变量,然后输出字符串?这里唯一的问题是Ember.Handlebars 与 Ember 一起工作;我只需要最终的、未绑定的 HTML。

【问题讨论】:

    标签: ember.js handlebars.js


    【解决方案1】:

    一种可能的方法是使用view 专用于呈现用户定义的模板。然后通过设置它的template 变量并重新渲染它,模板可以动态改变。

    例子,

    http://emberjs.jsbin.com/yexizoyi/1/edit

    hbs

    <script type="text/x-handlebars">
        <h2> Welcome to Ember.js</h2>
    
        {{outlet}}
      </script>
    
      <script type="text/x-handlebars" data-template-name="test">
        this is the test,
    
        {{view view.userTemplate}}
    
        <button {{action "changeTemplate" 1 target="view"}}>change to Template 1</button>
        <button {{action "changeTemplate" 2 target="view"}}>change to Template 2</button>
      </script>
    

    js

    App.Router.map(function() {
      this.route("test");
    });
    
    App.IndexRoute = Ember.Route.extend({
      beforeModel: function() {
        this.transitionTo("test");
      }
    });
    
    App.UserTemplateView = Ember.View.extend({
      template:Ember.Handlebars.compile("initial default template <b>{{view.parentView.parentVar}}</b>")
    });
    
    App.TestView = Ember.View.extend({
      parentVar:"this is a parent variable",
      userTemplate:App.UserTemplateView.create(),
      actions:{
        changeTemplate:function(templateId){
          if(templateId===1){
            this.get("userTemplate").set("template",Ember.Handlebars.compile("this is template 1 <b>{{view.parentView.parentVar}}</b>"));
            this.get("userTemplate").rerender();
          }else{
            this.get("userTemplate").set("template",Ember.Handlebars.compile("this is template 2 <b>{{view.parentView.parentVar}}</b>"));
            this.get("userTemplate").rerender();
          }
        }
      }
    });
    

    这也可以通过使用ContainerViewhttp://emberjs.com/guides/views/manually-managing-view-hierarchy/来实现

    例如, http://emberjs.jsbin.com/luzufixi/1/edit

    edit - 对 cme​​ts 的补充和 Sam Selikoff 使用助手的良好解决方案

    这是使用前一个概念的一个更粗略的示例,以及路由器模型和由通用View 对象支持的{{view}} 助手,即PreviewTemplateView

    http://emberjs.jsbin.com/tonapaqi/1/edit

    http://emberjs.jsbin.com/tonapaqi/1#/test/1

    http://emberjs.jsbin.com/tonapaqi/1#/test/2

    hbs - 使用所需上下文调用 {{view}} 助手,如果它包含 template 属性,则初始默认模板将更改。

    {{view App.PreviewTemplateView contextBinding="this"}}
    

    js

    App.Router.map(function() {
      this.route("test",{path:"test/:tmpl_id"});
    });
    
    App.IndexRoute = Ember.Route.extend({
      beforeModel: function() {
        this.transitionTo("test",1);
      }
    });
    App.TestRoute = Ember.Route.extend({
      model:function(params){
        if(params.tmpl_id==1){
          return {template:"this is template 1 <b>{{view.parentView.parentVar}},param from context of model:{{someParams.param1}}</b>",someParams:{param1:"p1",param2:"p2"}};
        }else{
          return {template:"this is template 2 <b>{{view.parentView.parentVar}},param from context of model:{{someParams.param2}}</b>",someParams:{param1:"p1",param2:"p2"}};
        }
      }
    
    });
    
    App.PreviewTemplateView = Ember.View.extend({
        template:Ember.Handlebars.compile("initial default template"),
      init:function(){
        this._super();
        this.refreshTemplate();
      },
      refreshTemplate:function(){
        this.set("template",Ember.Handlebars.compile(this.get("context").get("template")));
        this.rerender();
      }.observes("context.template")
    });
    
    App.TestView = Ember.View.extend({
      parentVar:"this is a parent variable"
    });
    

    【讨论】:

    • 非常感谢!我无法弄清楚如何从(比如说)一条路线设置userTemplate。有任何想法吗? (不确定如何从this.render 获取正在渲染的实例)
    • @SamSelikoff 如果模板依赖于路由或模型,那么模板值可以设置为控制器的变量,视图可以访问该变量以更改template财产。我喜欢你的解决方案,使用助手更通用。
    【解决方案2】:

    我最终选择了 Handlebars 助手。似乎更灵活一些。

    我正在使用 EAK 和 Coffeescript:

    helper = Ember.Handlebars.makeBoundHelper (template, context) ->
    
    dummy = Ember.View.extend
      context: context
      template: Ember.Handlebars.compile template
    view = dummy.create()
    $elem = null
    Ember.run ->
      $elem = $('<div>')
      view.appendTo($elem)
    
    return new Handlebars.SafeString $elem.html()
    

    现在我可以在任何模板中编写

    {{preview-template template context}}
    

    其中template 是(可能是用户生成的)模板,context 是数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-23
      • 1970-01-01
      • 1970-01-01
      • 2015-07-23
      • 1970-01-01
      • 1970-01-01
      • 2012-12-02
      • 1970-01-01
      相关资源
      最近更新 更多