干燥Ember Views的最佳做法?

时间:2013-03-04 07:22:55

标签: ember.js handlebars.js

我是Ember.js的新手,对于清理代码有疑问。我使用的是Ember(v1.0.0-rc.1),Handlebars(" 1.0.0-rc.3")和Bootstrap(v2.3.1)。

使用下面的一个模板:

<form class="form-horizontal">

  <div class="control-group">
    <label class="control-label" for="inputEmail">Name</label>
    <div class="controls">
      {{view Ember.TextField valueBinding="name" id="inputEmail"}}
    </div>
  </div>

  <div class="control-group">
    <label class="control-label" for="inputNumber">ID Number</label>
    <div class="controls">
      {{view Ember.TextField valueBinding="number" id="inputNumber"}}
    </div>
  </div>

  <div class="control-group">
    <label class="control-label" for="inputContactName">Contact Name</label>
    <div class="controls">
      {{view Ember.TextField valueBinding="invoiceContactName" id="inputContactName"}}
    </div>
  </div>

  <div class="control-group">
    <label class="control-label" for="inputContactEmail">Contact Email</label>
    <div class="controls">
      {{view Ember.TextField valueBinding="invoiceContactEmail" id="inputContactEmail"}}
    </div>
  </div>
</form>

现在我有了这个丰富的视图框架,所有重复感觉都很脏!问题是模板的性质......我需要传递我绑定的对象,并改变模板将呈现的值。我的第一次尝试是#34; nest&#34;把手模板......这很混乱,我没有到达任何地方。我的第二次尝试是创建一个&#34;预处理器&#34;在Handlebars编译之前修改模板字符串......这看起来更干净,但根本不起作用......当&#34;模板&#34;在视图上被调用我们脱离了上下文。示例如下:

App.BootstrapTextField = Ember.View.extend({
  displayLabel: null, 
  valueToBind: null,
  classNames: ['control-group'],

  templateString: '<div class="control-group">' +
                    '<label class="control-label" for="input##valueToBind##">##displayLabel##</label>' +
                    '<div class="controls">' +
                      '{{view Ember.TextField valueBinding="##valueToBind##" id="input##valueToBind##"}}' +
                    '</div>' +
                  '</div>',

  preprocessTemplate: function () {
   var template =  this.templateString.replace(/##valueToBind##/g, this.get('valueToBind'));
   return template.replace(/##displayLabel##/, this.get('displayLabel'));
  },

  template: Ember.Handlebars.compile(this.preprocessTemplate())
})

错误:

Uncaught TypeError: Object [object global] has no method 'preprocessTemplate'

我的问题是:清理它的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

我认为使用带有布局属性的Ember Mixin可以帮助您实现您想要的效果。

App.BootstrapMixin = Em.Mixin.extend({
  layout: Em.Handlebars.compile(
              '<div class="control-group">' +
                '<label class="control-label" for="input##valueToBind##">##displayLabel##</label>' +
                '<div class="controls">' +
                  '{{yield}}' +
                '</div>' +
              '</div>')

})

然后您可以像这样定义自定义引导程序视图:

 App.BootstrapTextField = Em.TextField.extend(App.BootstrapMixin, {
    // your custom logic
 })

并将其包含在模板中,如下所示:

<form class="form-horizontal">
   {{view App.BootstrapTextField valueBinding="name" id="inputEmail"}}
   .. 
   ..
</form>

我没有确切地检查确保这一切都有效(可能有些愚蠢的错误或其他),但我认为一般的想法应该足以让你开始。希望这有帮助!

答案 1 :(得分:1)

在另一篇文章中找到答案。问题是处理模板以使标签的“for”属性与input元素的id元素匹配。这是帖子:

Using Ember.js text field ids for a <label> tag

我的解决方案:

App.BootstrapTextField = Ember.View.extend({
  displayLabel: null, 
  classNames: ['control-group'],

  template: Ember.Handlebars.compile('' +
              '<label class="control-label" {{bindAttr for="view.textField.elementId"}}>' +
              '{{view.displayLabel}} </label>' +
              '<div class="controls">{{view Ember.TextField valueBinding=view.value viewName="textField"}}</div>'
                                    ),
})

使用以下模板调用:

{{view App.BootstrapTextField valueBinding='somefield' displayLabel='FieldName'}}