Ember-cli Component show records to component template - ember.js

test-component.js
import Ember from 'ember';
export default Ember.Component.extend({
store: Ember.inject.service(),
showLang: Ember.on('init', function() {
var store = this.get('store');
return store.findAll('language');
}),
});
I checked with console and yes they show
XHR finished loading: GET "http://127.0.0.1:8000/languages".
So backend recognize my test-component function.
Now in test-component.hbs I have
{{#each showLang as |lang| }}
<li>{{lang.title}}</li>
{{/each}}
The result was empty. How can I do so data could show up in test-component.hbs?

First of all - you should do it in route and pass data as model to component, but if you really want to do this in component you can do so:
test-component.js:
import Ember from 'ember';
export default Ember.Component.extend({
store: Ember.inject.service(),
showLang: Ember.on('init', function() {
this.get('store').findAll('language').then(languages => this.set('languages', languages));
})
});
test-component.hbs:
{{#each languages as |lang| }}
<li>{{lang.title}}</li>
{{/each}}

Related

Pass value from `route` to template

I am trying to pass a value from route to template. But I am not able to get the result. how to pass the value from route to template.
here is my try:
my route.js :
import Ember from 'ember';
export default Ember.Route.extend({
name:"SCB"
});
here is my hbs file :
<h1>My Name is : {{name}}</h1>
Live Twiddle
The template is mapped to the controller, not the route. To accomplish this, use the setupController function:
import Ember from 'ember';
export default Ember.Route.extend({
setupController(controller) {
this._super(...arguments);
controller.set('name', 'SCB');
}
});
Another solution would be to use a controller:
import Ember from 'ember';
export default Ember.Controller.extend({
name: 'SCB'
});
You need to set a variable in Controller:
export default Controller.extend({
name:"SCB"
});
And then set it in Route:
this.set('controller.name', 'newName');
And in hbs you can access it like:
{{ name }}

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.

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

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).

Im trying to understand ember and ember cli conventions and file structure

I have set up a simple api and a new ember app using ember cli
However, while I can get a full list of 'items' to appear, I can't get a single item to work using params.
I have my files set up like the following:
/models
item.js
/routes
/items
index.js
show.js
/templates
/items
index.hbs
show.hbs
application.hbs
index.hbs
items.hbs
router.js
For reference, here is what I have in the files
I set up my models/item.js a follows:
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string')
});
I added my code to my router.js
import Ember from 'ember';
import config from './config/environment';
var Router = Ember.Router.extend({
location: config.locationType
});
Router.map(function() {
this.route('items', function() {
this.route('show', { path: '/:item_id' });
});
});
export default Router;
Then I created my templates/index.hbs
{{outlet}}
And finally, added my templates/items/index.hbs
<ul>
{{#each model as |item|}}
<li>
{{#link-to 'items.show' item}}
{{item.name}}
{{/link-to}}
</li>
{{/each}}
</ul>
This works as intended.
However, when I click a link (/items/1), it no longer performs as expected. It will show the items/show.hbs correctly assuming I do no use any handlebars variables ({{item.name}}). For example, If I just include text, this is my items/show.hbs it will display the text. When I add in, {{name}} it displays a blank page
Here is my templates/items/show.hbs
{{name}}
and my routes/items/show.js
import Ember from 'ember';
export default Ember.Route.extend({
model(params) {
return this.store.queryRecord('item', params.item_id);
}
});
What am I doing wrong?
Thanks in advance!
It looks like you're not using reference to model when using it in template
Here is my templates/items/show.hbs
{{name}} < This is a model's property- name
Correct usage: {{model.name}}
and my routes/items/show.js
import Ember from 'ember';
export default Ember.Route.extend({
model(params) {
return this.store.queryRecord('item', params.item_id);
}
});
Way of using hash
return Ember.RSVP.hash({
something: store.find('y', { study: params.study_id }),
somethingElse: store.find('x', 1),
});

Ember computed property to return first X number of items from list

I have a one-to-many relationship (using Ember Data). All I want to do is list the first N number of items from that relationship in an overview (index) template. I'm trying to use the Array.slice method but it doesn't seem to return anything at all.
Here's what I have right now:
models/account.js
// Account model
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
notes: DS.hasMany('note', { async: true })
});
models/note.js
// Note model
import DS from 'ember-data';
export default DS.Model.extend({
body: DS.attr('string'),
date: DS.attr('number'), // unix timestamp
account: DS.belongsTo('account', { async: true })
});
controllers/account/index.js
// account/index controller
import Ember from 'ember';
export default Ember.ObjectController.extend({
firstNotes: function() {
return this.get('notes').slice(0,2);
}.property('notes')
});
templates/account/index.hbs
{{!-- this lists all the associated `Notes` --}}
{{#each notes}}
{{date}}<br>
{{body}}
{{/each}}
{{!-- this doesn't list anything!!?? --}}
{{#each firstNotes}}
{{date}}<br>
{{body}}
{{/each}}
I figured this out just as I was about to post it so I figured I'd answer it...
All I was missing was a #each in the computed property dependency. So it works as expected with this:
firstNotes: function() {
return this.get('notes').slice(0,2);
}.property('notes.#each')
Simple.