【问题标题】:Best way to bind textfield to a model in ember将文本字段绑定到 ember 中的模型的最佳方法
【发布时间】:2013-09-10 16:57:36
【问题描述】:

我试图弄清楚如何将模型绑定到文本字段,以便在更新文本字段中的值时,也更新底层模型(并将 PUT 请求发送到适当的 API)。从文档 ember-data 似乎能够做到这一点,但我无法将我的自定义文本字段连接到控制器/模型。

这是我的模型的外观:

AS.Run = DS.Model.extend({
'analyticsPlan' : DS.attr('string'),
'commandScript' : DS.attr('string'),
'parameters'    : DS.hasMany('parameter')
});

AS.Parameter = DS.Model.extend({
'name'          : DS.attr('string'),
'type'          : DS.attr('string'),
'description'   : DS.attr('string'),
'value'         : DS.attr('string'),
'default'       : DS.attr('string'),
'analyticRun'   : DS.belongsTo("run")
});

这是我的模板:

<table style="width:100%;" class="affi-table">
        <thead>
            <tr class="ui-state-default">
                <th style="width:120px;">Parameter Type</th>
                <th style="width:120px;">Parameter Name</th>
                <th>Description</th>
                <th>Default value</th>
                <th>Value</th>
            </tr>
        </thead>
        <tbody>
              {{#each parameter in parameters}}
                <tr>
                    <td>{{parameter.type}}</td>
                    <td>{{parameter.name}}</td>
                    <td>{{parameter.description}}</td>
                    <td>{{parameter.default}}</td>
                    <td>{{view AS.AnalyticsParameterTextField valueBinding="parameter.value" placeholder="" nameBinding="parameter.name" style="width:200px;"}}</td>
                </tr>
              {{/each}}
        </tbody>
    </table>

AnalyticsParameterTextField 定义为:

AS.AnalyticsParameterTextField = Ember.TextField.extend({
attributeBindings: ['name','style'],

focusOut: function(evt) {
    var paramName = this.get('name');
    var paramValue = this.value;

    console.log(this.get('controller'));//this returns <AS.AnalyticsParameterTextField:ember568> which is not the controller
    //this was working before when I was not using ember model objects, but when I was just pulling the json data right out from a rest end point

}
});

我真的需要一些帮助来弄清楚如何在 AnalyticsParameterTextField 中获取控制器。一旦解决了这个问题,我需要弄清楚如何更新底层模型并发出服务器 API 请求来更新数据库。我想我可以发出 ajax 请求来更新底层数据库,但在 ember-data 版本 1 中,我想我可能可以在我的控制器中使用类似的东西:

var p = this.get('store').find('parameter',somekey)  
p.save();

更新:

我现在可以使用Ember TextField valueBinding with dynamic property 中提供的示例进行操作 但似乎必须有更好的方法来解决这个问题。

我的模板看起来像:

{{#each parameter in parameters}}
  <tr>
    <td>{{parameter.type}}</td>
    <td>{{parameter.name}}</td>
    <td>{{parameter.description}}</td>
    <td>{{parameter.default}}</td>
    <td>{{view AS.AnalyticsParameterTextField paramValueBinding="parameterValue" valueBinding="parameter.value" placeholder="" nameBinding="parameter.name" style="width:200px;"}}</td>
</tr>
{{/each}}

文本字段代码如下所示:

AS.AnalyticsParameterTextField = Ember.TextField.extend({
attributeBindings: ['name','style'],
paramValue : {},
updateValues: function() {
    var name = this.get('name');
    var val = this.value;
    this.set('paramValue',{"name":name,"value":val});
}.observes('value')
});

我的控制器看起来像:

AS.AnalyticsConfigController = Ember.ObjectController.extend({

runId : null,
parameterValue : null,

/*
* This function is called every time a parameter is updated/changed.
* It makes API call to appropriate rest end point("/analytics/runs/:runId/parameters/:name" to be specific)
*/
updateRunParameter:function(){
    var store = this.get('store');
    var runId = this.get('runId');

    /*
    * defining namespace rule for the "parameter" model here because the namespace depends on the dynamic parameter value "runId"
    */
    AS.ParameterAdapter = DS.RESTAdapter.extend({
        namespace: AS.baseURL.substr(1)+"analytics/runs/"+runId
    });

    store.find('parameter', 'historyDir').then(function(parameterObject) {
        //once the promise is resolved, save the parameter object
        parameterObject.save();
    });
}.observes('parameterValue')
});

但我必须说我讨厌这种方法,必须有一种更清洁的方法来做到这一点。现在,当文本字段值更新时,它会更新自己的属性,进而更新控制器属性,然后控制器会监视此属性以进行适当的 API 调用。

【问题讨论】:

    标签: ember.js ember-data


    【解决方案1】:

    根据指南的入门部分所说,您应该使用 {{input}} 帮助器而不是自定义视图 http://emberjs.com/guides/getting-started/marking-a-model-as-complete-incomplete/)。它应该是这样的:

    <td>{{input type="text" value=parameter.value}}</td>
    

    控制器知道哪条记录在哪里,这就是为什么它可以“神奇地”在输入的 HTML 元素与其对应记录的值之间建立链接。

    现在对于 focusOut 部分,我将使用 td 上的 {{action}} 助手来捕获事件(请阅读此事件类型:http://emberjs.com/guides/templates/actions/#toc_specifying-the-type-of-event),如下所示:

    <td {{action "focusOut" parameter on="focusOut">{{input type="text" value=parameter.value}}</td>
    

    必须在控制器中设置“focusOut”动作,参数是您发送给函数的模型,on="focusOut" 是动作响应的事件。 将参数发送到动作“focusOut”的好处是,在控制器的 focusOut 动作中,您可以简单地调用:

    ---- controller code ----
    
    focusOut: function(model){
     model.save();
    }
    
    ---- controller code ----
    

    如果您使用的是 Ember-Data,商店会知道您的模型和要使用的适配器,因此您只需调用 save(它位于 Ember-Data API 中的 DS.Model 类下)。

    由于我现在只使用 FIXTURES,我不能真正谈论适配器,但您可以查看指南中的模型部分,它可能会对您有所帮助。

    【讨论】:

    • 太棒了,我只是做了一点改变:{{input type="text" value=parameter.value}} 我知道我做错了事。感谢 Simon 向我展示了正确的方法,现在我的控制器看起来也超级干净。
    • 我刚刚意识到,当在 keyPress 或 KeyUp 上设置操作时,它的行为不正常。只有当我们失去对输入元素的关注时才会触发该事件。
    • 如果您希望您的输入字段对多个事件做出反应,您需要创建一个扩展 Ember.Select 类的自定义视图并设置事件管理器 (emberjs.com/api/classes/Ember.View.html) 以监听您想要的事件
    • 是的,你是对的,我能够通过使用如下视图来获得所需的行为:{{#view AS.MyView dataBinding="parameter"}}{{input type="text " value=parameter.value class="smallSelect" name=parameter.name}}{{/view}}。在我看来,我所要做的就是创建 keyUp 函数。谢谢。
    猜你喜欢
    相关资源
    最近更新 更多
    热门标签