1

我正在尝试根据模型中属性的当前值呈现不同的车把模板,并且可能有很多选项(因此我宁愿不使用很多{{#if}}s)。我能想到的最好的事情是:

Ember.Handlebars.registerBoundHelper('selectorType', function(name, options) {
  return Ember.Handlebars.compile("{{template _selectors_" + name + "}}")(options.contexts[0], options);
});

我在我的模板中使用它,例如:

{{selectorType selector.name}}

(而不是像一百个{{#if}}

问题是我在渲染期间收到此错误:“您不能在渲染过程之外使用 appendChild”

显然我做错了什么。这样做的正确方法是什么?

4

2 回答 2

0

我最终使用带有动态子视图的 ContainerView 解决了这个问题,请参阅Ember.js 动态子视图以了解如何进行讨论。

相关代码是(coffeescript):

App.SelectorType = Ember.Object.extend
  name: null
  type: null
  typeView: null
  options: null

App.SelectorTypes = [
  App.SelectorType.create(
    name: 'foo'
    type: 'bar'
  ) #, more etc
]

App.SelectorTypes.forEach (t) ->
  t.set 'typeView', Ember.View.create
    templateName: "selectors/_#{t.get('viewType')}_view"
    name: t.get('name')

App.SelectorDetailView = Ember.ContainerView.extend
  didInsertElement: ->
    @updateForm()

  updateForm: (->
    type = @get('type')
    typeObject = App.SelectorTypes.findProperty('type', type)
    return if Ember.isNone(type)

    view = typeObject.get('typeView')
    @get('childViews').forEach (v) -> v.remove()
    @get('childViews').clear()
    @get('childViews').pushObject(view)
  ).observes('type')

和模板:

  Selector Type:
  {{view Ember.Select
        viewName=select
        contentBinding="App.SelectorTypes"
        optionValuePath="content.type"
        optionLabelPath="content.name"
        prompt="Pick a Selector"
        valueBinding="selector.type"
  }}
<dl>
  <dt><label>Details</label></dt>
  <dd>
    {{view App.SelectorDetailView typeBinding="selector.type"}}
  </dd>
</dl>

不过,似乎太难了,有兴趣看到更好的解决方案!

于 2013-02-10T21:52:50.217 回答
0

我认为没有必要创建一个助手来做到这一点。您可以在视图中通过修改 来执行此操作,然后在更改templateName其后调用该rerender方法templateName

init: function() {
    this.set('templateName', 'firstOne');
    this._super();
},

click: function() {
    this.set('templateName', 'secondOne');
    this.rerender();
}

我们可以使用在模板渲染之前init设置为空的方法。templateName然后我们将调用该_super方法来完成将视图插入到 DOM 中。然后我们可以在点击事件上触发视图的变化。我们更新templateName变量,然后调用rerender()重新渲染这个特定的视图。

我已经为您设置了一个 JSFiddle 作为示例:http: //jsfiddle.net/pFkaE/尝试单击“第一个”。将视图更改为secondOne.

于 2013-02-07T16:23:12.943 回答