How can I update component value in controller or route with ember? - ember.js

My click-editable component like:
Template:
{{#if isEdit}}
<div class="input-group">
{{input type="text" value=editValue class="form-control"}}
<div class="input-group-btn">
<button type="button" class="btn no-margin-btn btn-info" {{action "updateValue"}}>{{fa-icon 'check'}}</button>
</div>
</div>
{{else}}
....
{{/if}}
And:
export default Ember.Component.extend({
tagName: "",
isEdit: false,
canEdit: true,
category: 'input',
editValue: Ember.computed.oneWay('value'),
actions:{
updateValue() {
this.sendAction('onUpdate', this.get('valueModel'), this.get('valueColumn'), this.get('editValue'), this.get('isEdit'));
}
}
});
Use in my template:
{{#each model.quotationWorkItems as |quotationWorkItem index|}}
{{click-editable valueModel=quotationWorkItem valueColumn='name' value=quotationWorkItem.name onUpdate=(action "updateInput")}}
{{/each}}
In the controller:
import Ember from 'ember';
export default Ember.Controller.extend({
....
actions: {
updateInput(updateModel, updateColumn, value, isEdit) {
updateModel.set(updateColumn, value);
updateModel.save().then(()=> {
this.get('model').reload();
this.set('isEdit', false);
}, ()=> {
alert('wrong');
});
}
}
})
Route:
import Ember from 'ember';
export default Ember.Route.extend({
...
model(params) {
return this.store.find('quotation', params.quotation_id);
},
setupController(controller, model) {
controller.set('model', model);
...
}
})
Quotation model:
import DS from 'ember-data';
export default DS.Model.extend({
quotationStocks: DS.hasMany('quotationStock'),
quotationWorkItems: DS.hasMany('quotationWorkItem'),
...
});
QuotationWorkItem model:
import DS from 'ember-data';
export default DS.Model.extend({
transactionType: DS.belongsTo('transactionType'),
quotation: DS.belongsTo('quotation'),
...
});
This code can update model value, but problem isEdit is the component value. When isEdit send to controller and set another value, it can not work. So I think can not change component value in ember controller?
this.set('isEdit', false);
The code can not work in controller. I'm using Ember 2.4.0.

You need to bind the controller isEdit property to the component isEdit property.
{{click-editable isEdit=isEdit valueModel=quotationWorkItem valueColumn='name' value=quotationWorkItem.name onUpdate=(action "updateInput")}}
This will overwrite the isEdit property in the component (data down).

Related

How can we get the original event in ember controller action

How can we get the original event in ember action while handling action inside controller?
Controller
import Ember from 'ember';
export default Controller.extend({
showDetails:function(id)
{
// I want like $(this).position().top
}
});
Template
{{#each item in list}}
<em {{action "showDetails" item.id bubbles=false}}></em>
{{/each}}
{{#each item in list}}
<em onclick={{action "showDetails" item.id}}></em>
{{/each}}
In controller,
import Ember from 'ember';
export default Controller.extend({
actions: {
showDetails(id, event) {
//i want like $(this).position().top
}
}
});

How to bind Route Property to Controller so that route property changes will reflect in controller

Changing isOpen property in route should reflect it in my component. How can we accomplish this ?.
Ember-Twiddle
routes/application.js
import Ember from 'ember';
export default Ember.Route.extend({
isOpen:true,
setupController(controller,model){
this._super(...arguments);
controller.set('isOpen',this.get('isOpen')); //whenever i set route property, will this update controller?
console.log('setupController');
},
actions:{
toggleOpen(){
console.log('before toggle - ',this.get('isOpen'));
this.toggleProperty('isOpen'); //changing this route property is not reflected in controller.
//this.controller.toggleProperty('isOpen'); //changing controller is reflecting.
console.log('after toggle - ',this.get('isOpen'));
}
}
});
controllers/application.js
import Ember from 'ember';
export default Ember.Controller.extend({
appName: 'Ember Twiddle'
});
templates/application.hbs
<h1>Welcome to {{appName}}</h1>
<br>
{{isOpen}}
{{my-component isOpen=isOpen toggleOpen='toggleOpen'}}
<br>
{{outlet}}
<br>
<br>
templates/components/my-component.hbs
my-component {{isOpen}}
<button {{action 'toggleOpen'}}> Toggle </button>
{{yield}}
components/my-component.js
import Ember from 'ember';
export default Ember.Component.extend({
actions:{
toggleOpen(){
this.sendAction('toggleOpen');
}
}
});
Because isOpen is a primitive typed property. No matter if it was an object. Sample Twiddle.
Or more simplistic one.

component cannot find action

I have a component that has a text field, like this
<div>
{{input type='text' insert-newline='postMessage' class="form-control" autofocus="true"}}
<input type="hidden" name="uid" value={{room.uid}}/>
</div>
the component that have this snippet, lives inside a route called room
export default Ember.Route.extend({
model(params){
this.store.findRecord('room', params.uid);
}
});
to handle the action in the input, I created a controller for the room:
app/controllers/room.js
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
postMessage(params){
console.log(params);
}
}
});
but when I hit enter, I get this error:
Uncaught Error: <chathub-ember#component:chat-room::ember1071> had no action handler for: postMessage
I tried to put this action in the route as well and didn't worked
In the room.hbs file,
{{my-component myAction='postMessage'}}
and then in my-component.js
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
postMessage(params) {
this.sendAction('myAction', params);
}
}
})

Disable button in Ember with return value of function

I've been trying to create an Ember Component with the latest version on Ember. Here is the part of the component I'm having trouble with though:
//app/templates/components/page-r.hbs
<div class="pager-container">
{{#each range as |page|}}
<button type="button" disabled={{isCurrentPage(page)}}>{{page}}</button>
{{/each}}
</div>
//app/components/page-r.js
import Ember from 'ember';
const PageR = Ember.Component.extend({
settings: Ember.computed('params.[]', function() {
return this.get('params')[0];
}),
range: [4,5,6],
currentPage: 1,
isCurrentPage(pageIndex) {
return this.currentPage === pageIndex;
},
});
PageR.reopenClass({
positionalParams: 'settings'
});
export default PageR;
There is more to the component than that, but my question is this:
Is it possible to make the disabled attribute update based off of the result of an action like I'm trying to do? If so, how?
The above code doesn't even compile, but I've tried a number of variations and haven't gotten any of them to work. I can get the disabled property to work based off a pure boolean value, but can't figure out how to get this to execute the function and utilize the boolean value that is returned from it to fuel the disabled attribute. Any help would be greatly appreciated!
You need to use another component to create the computed property.
// app/templates/components/page-r.hbs
<div class="pager-container">
{{#each range as |page|}}
{{page-button page=page currentPage=currentPage}}
{{/each}}
</div>
// app/templates/components/page-button.hbs
<button type="button" disabled={{isCurrentPage}}>{{page}}</button>
// app/components/page-r.js
import Ember from 'ember';
const { computed } = Ember;
const PageR = Ember.Component.extend({
settings: computed('params.[]', function() {
return this.get('params')[0];
}),
range: [4,5,6],
currentPage: 1
});
PageR.reopenClass({
positionalParams: 'settings'
});
export default PageR;
// app/components/page-button.js
import Ember from "ember";
const { computed } = Ember;
export default Ember.Component.extend({
tagName: 'span',
isCurrentPage: computed('currentPage', 'page', function() {
return this.get('currentPage') === this.get('page');
}),
});

Use ember-simple-validaiton to validate property on hasMany relation

this question is about particular plugin - ember-cli-simple-validation.
Lets assume that there is two models
User = DS.Model.extend({
name: DS.attr()
emails: DS.hasMany('email')
})
Email = DS.Model.extend({
address: DS.attr()
emails: DS.belongsTo('user')
})
and user dynamically create emails:
<button {{action 'createEmail'}}>Add Email</button>
{{#each model.emails as |email index|}}
{{input value=email.address}}
{{/each}}
is it possible to use ember-simple-validaiton in this situation to validate presence of address on each of the emails?
I tried to go with validateEach but getting an Error while processing route: profile self.get(...).forEach is not a function TypeError: self.get(...).forEach is not a function error on the https://github.com/toranb/ember-cli-simple-validation/blob/master/addon/mixins/validate.js#L66
controller:
import Ember from 'ember';
import {ValidationMixin, validateEach} from "ember-cli-simple-validation/mixins/validate";
var isLegit = function(address) {
return address && address.length > 3;
};
export default Ember.Controller.extend(ValidationMixin, {
emailAddressValidation: validateEach("model.emails", isLegit),
actions: {
createChildren: function(type) {
this.store.createRecord(type, {profile: this.get('model')});
},
});
template:
{{#each model.emails as |email index|}}
{{input value=email.address}}
{{#validation-error-field submitted=submitted field="address" model=mode.emails index=index validation="basic"}}invalid address{{/validation-error-field}}
{{/each}}
model:
import Ember from 'ember';
import DS from 'ember-data';
export default DS.Model.extend{
address: DS.attr(''),
kind: DS.attr(''),
contactable: DS.belongsTo('contactable', { polymorphic: true, inverse: 'emails', async: false }),
kindIsPrimed: false,
kindChanged: Ember.observer('kind', function () {
this.set('kindIsPrimed', true);
}),
addressIsPrimed: false,
addressChanged: Ember.observer('address', function () {
this.set('addressIsPrimed', true);
})
});
On the surface (without running the code) you might alter your hbs from this
{{#each model.emails as |email index|}}
{{input value=email.address}}
{{#validation-error-field submitted=submitted field="address" model=mode.emails index=index validation="basic"}}invalid address{{/validation-error-field}}
{{/each}}
to instead ...
{{#each model.emails as |email index|}}
{{input value=email.address}}
{{#validation-error-field submitted=submitted field="address" model=email index=index validation="basic"}}invalid address{{/validation-error-field}}
{{/each}}
In the validateEach scenario (for array validation) you need to set the model and index on each iteration. The model should still be the individual model (not the array itself).
Another example that's tested in the addon for reference
https://github.com/toranb/ember-cli-simple-validation/blob/master/tests/dummy/app/templates/many.hbs