I am trying to figure out how to bind model to textfield so that when the value in the text-field is updated, the underlying model is also updated(and send PUT request to proper API). From the documentation ember-data seems to be capable to doing this, but I couldn't connect my custom text field to controller/model.
Here is how my models look:
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")
});
And here is my template:
<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 is defined as:
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
}
});
I could really use some help in figuring out how to get the controller in AnalyticsParameterTextField. Once that is sorted out, I need to figure out how to update the underlying model and also make server API requests to update the database. I think I can make ajax request to update the underlying database but in ember-data version 1 I think I can probably use something like this in my controller:
var p = this.get('store').find('parameter',somekey)
p.save();
UPDATE :
I got things to work for now using the example provided in Ember TextField valueBinding with dynamic property But it seems likes there must be a better approach to solve this.
My template looks like:
{{#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}}
The textfield code looks like:
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')
});
And my controller looks like:
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')
});
But I must say I detest this approach, there must be a cleaner way to do this. Right now when the text field value gets updated, it updates its own property which in turn updates the controller property and then controller watches this property to make appropriate API calls.
From what the Getting Started part of the guides say, you should use the {{input}} helper instead of a custom view http://emberjs.com/guides/getting-started/marking-a-model-as-complete-incomplete/). It should look like this:
<td>{{input type="text" value=parameter.value}}</td>
The controller knows which record is where, that's why it can "magically" make the link between an input HTML element and its corresponding record's value.
Now for the focusOut part, I would use the {{action}} helper on the td to catch the event (read this for the types of event: http://emberjs.com/guides/templates/actions/#toc_specifying-the-type-of-event) , like so:
<td {{action "focusOut" parameter on="focusOut">{{input type="text" value=parameter.value}}</td>
The "focusOut" action has to be set up in your controller, parameter is the model you send to the function and on="focusOut" is the event the action responds to. The benefit of sending the parameter to the action "focusOut" is that in the focusOut action of your controller you can simply call:
---- controller code ----
focusOut: function(model){
model.save();
}
---- controller code ----
That's if you're using Ember-Data, the store knows about your model and the adapter to use so you can just call save (it's in the Ember-Data API, under the DS.Model class).
Since I'm only using FIXTURES for now, I can't really say anything about Adapters but you can take a look at the Models part of the guides, it might help you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With