1

http://jsfiddle.net/4ZyBM/6/

我想为我的 UI 元素使用 Bootstrap,我现在正尝试将某些元素转换为 Ember 视图。我有以下问题:

我将输入元素嵌入到具有给定类(控制组)的 DIV 中。如果该字段发生验证错误,那么我想向 DIV 添加一个额外的类“错误”。

我可以基于 Ember.TextField 创建一个视图,并指定如果发生错误,ClassNameBinding 应该是“错误”,但问题是类是输入元素的集合,而不是 DIV 的集合。

您可以通过在字段中输入非字母数字字符来测试这一点。我想看到红色的 DIV 边框,而不是输入字段的边框。

HTML:

<script type="text/x-handlebars">
    <div class="control-group">
    {{view App.AlphaNumField valueBinding="value" type="text" classNames="inputField"}}
    </div>
</script>

JS:

App.AlphaNumField = Ember.TextField.extend({
  isValid: function () {
    return /^[a-z0-9]+$/i.test(this.get('value'));
  }.property('value'),
  classNameBindings: 'isValid::error'
})

我可以在父元素或最接近输入的元素上设置 classNameBindings 吗?在jQuery中,我会使用:

$(element).closest('.control-group').addClass('error');
4

2 回答 2

2

这里的问题是,如果不使用 jQuery,您将无法轻松访问您周围的包装 div Ember.TextField。另外值得一提的是,可能还有一百种方法可以做到这一点,但我能想到的最简单的解决方案是创建一个简单Ember.View的包装器并检查底层子视图的有效性。

模板

{{#view App.ControlGroupView}}
  {{view App.AlphaNumField 
    valueBinding="value" 
    type="text" 
    classNames="inputField" 
    placeholder="Alpha num value"}}
{{/view}}

Javascript

App.ControlGroupView = Ember.View.extend({
  classNameBindings: 'isValid:control-group:control-group-error',
  isValid: function () {
    var validFields = this.get('childViews').filterProperty('isValid', true);
    var valid = validFields.get('length');
    var total = this.get('childViews').get('length')
    return (valid === total);
  }.property('childViews.@each.isValid')
});

App.AlphaNumField = Ember.TextField.extend({
  isValid: function () {
    return /^[a-z0-9]+$/i.test(this.get('value'));
  }.property('value')
});

CSS

.control-group-error {
  border:1px solid red;
  padding:5px;
}

.control-group {
  border:1px solid green;
  padding:5px;
}

工作演示

关于 bootstrap-ember 集成,为了 DRY,您还可以查看此 ember-addon:https ://github.com/emberjs-addons/ember-bootstrap

希望能帮助到你。

于 2013-08-22T00:24:24.467 回答
1

我认为这是更灵活的方法:

Javascript

Boostrap = Ember.Namespace.create();

为了简化每个事物FormControl都有属性:标签、消息和实习控制。所以你可以扩展它并指定你想要的控件。像组合框,单选按钮等。

Boostrap.FormControl = Ember.View.extend({
    classNames: ['form-group'],
    classNameBindings: ['hasError'],    
    template: Ember.Handlebars.compile('\
      <label class="col-lg-2 control-label">{{view.label}}</label>\
      <div class="col-lg-10">\
        {{view view.control}}\
        <span class="help-block">{{view.message}}</span>\
      </div>'),
    control: Ember.required()
});

是其中Boostrap.TextField一种实现,您的组件是Ember.TextField. 因为那Boostrap.TextField是一个实例Ember.View而不是Ember.TextField直接。我们使用 委托值Ember.computed.alias,因此您可以valueBinding在模板中使用。

Boostrap.TextField = Boostrap.FormControl.extend({      
    control: Ember.TextField.extend({
        classNames: ['form-control'],
        value: Ember.computed.alias('parentView.value')
    })
});

这里没什么特别的,只需创建默认值 tagName=form 和 classNames=form-horizo​​ntal,因为每次都不记得。

Boostrap.Form = Ember.View.extend({
    tagName: 'form',
    classNames: ['form-horizontal']    
});

创建一个子类 Boostrap.Form并将验证委托给控制器,因为它必须是关于验证的知识。

App.LoginFormView = Boostrap.Form.extend({
    submit: function() {
        debugger;
        if (this.get('controller').validate()) {
            alert('ok');
        }
        return false;
    }
});

这是执行验证逻辑和处理的地方。所有使用绑定而不需要触摸 dom。

App.IndexController = Ember.ObjectController.extend({
    value: null,
    message: null,
    hasError: Ember.computed.bool('message'),
    validate: function() {
        this.set('message', '');
        var valid = true;
        if (!/^[a-z0-9]+$/i.test(this.get('value'))) {
            this.set('message', 'Just numbers or alphabetic letters are allowed');
            valid = false;
        }
        return valid;
    }
});

模板

<script type="text/x-handlebars" data-template-name="index">
    {{#view App.LoginFormView}}            
        {{view Boostrap.TextField valueBinding="value" 
                                label="Alpha numeric" 
                                messageBinding="message"
                                hasErrorBinding="hasError"}}
        <button type="submit" class="btn btn-default">Submit</button>
    {{/view}}
</script>

这里有一个现场演示

更新

就像@intuitivepixel 所说,ember-boostrap 已经实现了这个。因此,如果您不想在 ember-boostrap 中有依赖项,请考虑我的示例。

于 2013-08-22T00:04:54.947 回答