【问题标题】:Ember input de-focus clears model valueEmber 输入散焦清除模型值
【发布时间】:2014-12-11 03:47:17
【问题描述】:

我有一个带有文本输入的 ember 模板和一个绑定到相同值的 select 视图。

{{input value=myValue}}
{{view "select" 
    content=myOptions 
    value=myValue 
    optionLabelPath="content.name" 
    optionValuePath="content.id"}}

我提供模型数据来支持这些选项

window.App = Ember.Application.create();

App.IndexRoute = Ember.Route.extend({
    model: function() { 
        return {
            myValue: 2,
            myOptions: [
                { name: 'a', id: 1 }, 
                { name: 'b', id: 2 },
                { name: 'c', id: 3 },
            ]
        }
    },
});

我已经为它创建了一个小提琴here

该值最初显示正常。但是,如果我聚焦输入框,然后按箭头键或通过单击输入框使其失焦,则该值消失(输入框变为空白,选择框显示未选择任何值)。

这个问题发生在一个更大的项目中,但上面的代码是我提炼出来的精髓。似乎删除选择视图会使问题消失。我已经搜索过,但找不到任何材料说明为什么会发生这种情况。

我的问题是:为什么我会看到这种行为,我应该采取不同的做法吗?

【问题讨论】:

    标签: ember.js input


    【解决方案1】:

    我根本无法说出这种行为的原因。有一些关于 Ember 的 select helper 的讨论,特别是 valueBinding 与 selectionBinding 的使用,值得一看(以及一个未解决的错误):

    https://github.com/emberjs/data/issues/82

    https://github.com/emberjs/ember.js/issues/482

    也就是说,将输入和选择绑定到相同的值似乎是一种奇怪的交互。虽然这不是您(或我的)理想的答案,但可以与一些观察者一起解决它并使用中介来进行链接:

    window.App = Ember.Application.create();
    App.SomeType = Ember.Object.extend({
        myValue: null,
        myObj: null,
        objChanged: function() {
            var o = this.get('myObj');
            if(!o) {
                return;
            }
            this.set('myValue', o.id);
        }.observes('myObj'),
        valChanged: function() {
            this.set('myObj', this.get('myOptions')[this.get('myValue')-1]);
        }.observes('myValue'),
        myOptions: null,
    });
    App.IndexRoute = Ember.Route.extend({
        model: function() { 
            var o = App.SomeType.create({
                myValue: 2,
                myOptions: [
                    { name: 'a', id: 1 }, 
                    { name: 'b', id: 2 },
                    { name: 'c', id: 3 },
                 ],
                });
                o.set('myObj', o.get('myOptions')[1]);
                return o;
            },
        }
    );
    

    HTML:

    <script type="text/x-handlebars" data-template-name="index">
        <h1>Test</h1>
        {{input valueBinding=myValue}}
        {{view "select" 
            contentBinding=myOptions 
            selectionBinding=myObj
            optionLabelPath="content.name"}}
    </script>
    

    我在你的小提琴中试过了,它似乎运行正常。它只是从 Ember 手中夺走了该值的直接绑定。这种复杂/间接的绑定似乎有问题。

    【讨论】:

    • 那么,在这种情况下,您是说selectionBindingvalueBinding 效果更好? selectionselectionBinding 有区别吗?
    • 一般来说,如果事情有可能从任何一方发生变化,请使用 xBinding。也就是说,如果视图可能会修改值并且您希望看到它反映在模型中,或者某些东西可能会更改模型并且您希望在视图中看到它。
    • 是的,在这种情况下,我选择了选择而不是值,因为我认为当前的实现不能非常干净地使用 optionValuePath。所以在这里我更喜欢将视图的选择作为一个整体对象绑定,并自己处理将值放在正确的位置。
    • 到目前为止,我的解决方案是按照您的建议使用selectionBinding,然后使用 Ember Data 的 belongsTo 将持久 ID 映射到模型的属性值(而不是手动管理它)。到目前为止,这似乎有效。我将接受您的回答,因为到目前为止,如果 (A) 您需要在模型中而不是对象中包含 ID,并且 (B) 您没有使用 Ember Data,您似乎可以做的最好的事情。跨度>
    【解决方案2】:

    我想与其他看到此问题的人分享我最终得到的解决方案。

    首先,我使用 Ember Data 来定义我的模型,并使用夹具来定义示例值:

    App.MyOption = DS.Model.extend({
        name: DS.attr('name')
    });
    
    App.MyOption.FIXTURES = [
        { name: 'a', id: 1 }, 
        { name: 'b', id: 2 },
        { name: 'c', id: 3 },
    ];
    
    App.MyModel = DS.Model.extend({
        myValue: DS.belongsTo('myOption')
    });
    
    App.MyModel.FIXTURES = [
        { 
            id: 1,
            myValue: 2
        }
    ];
    

    在模型中myValue不是DS.attr('number'),而是belongsTo,这意味着当Ember Data加载fixtures(或者可能是任何服务器数据)时,它会将myValue: 2转换成实际的对象表示值 ({ name: 'b', id: '2'})。所以 Ember Data 处理的是 ID 到对象的映射,而不是将 ID 暴露给模板(这方面似乎有 bug)。

    然后,当我们在路由中加载模型时,我们使用 Ember Data 从商店(在本例中为我们的固定装置)执行此加载:

    App.IndexRoute = Ember.Route.extend({
        model: function() { 
            return Ember.RSVP.hash({
                myModel: this.store.find('myModel', 1),
                myOptions: this.store.find('myOption')
            });
        },
    });
    

    现在在模板中,我们按照 Carl 的建议使用 selectionBindingmyValue 作为 对象 而不是 ID 绑定到:

    {{input value=myModel.myValue.name}}
    {{view "select" 
        content=myOptions 
        selectionBinding=myModel.myValue 
        optionLabelPath="content.name"}}
    

    Here is a fiddle 一起显示解决方案。

    注意:此解决方案在编辑文本输入的含义方面具有不同的行为。以前它是一种手动更改选定对象的方法,而现在它是一种更改当前选定对象名称的方法。在我的特殊情况下,这不是问题,但在你的情况下,这可能是。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-18
      • 1970-01-01
      • 2016-11-09
      • 2017-03-10
      • 1970-01-01
      • 1970-01-01
      • 2012-02-19
      • 2017-07-31
      相关资源
      最近更新 更多