I have a post route post.index inside the route,
import Ember from 'ember';
export default Ember.Route.extend({
model() {
this.get('store').findAll('post');
}
});
Inside the post hbs,
{{debugger}}
<ul>
{{#each model as |post|}}
{{post/post-item
post=post
}}
{{/each}}
</ul>
However, when I inspect the context using debugger I see null for model.
Why?
Your model should return the result.
model() {
return this.get('store').findAll('post');
}
Related
I have a route in my app (repo) where i fetch bookings belonging to a user, I also include rentals and rentals.rental-ratings in the request. Now, a rental (which belongsTo a Booking) hasMany rentalRatings, and rentalRatings belongsTo Users. In the template I have a component that accepts booking and a rentalRating as arguements. How can I get a rating that belongsTo the booking and the currentUser?
Bookings route:
import Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
export default Ember.Route.extend(AuthenticatedRouteMixin, {
sessionAccount: Ember.inject.service(),
model() {
const currentUser = this.get('sessionAccount.currentUser');
return this.get('store').query('booking', {
filter: {
'user_id': currentUser.id
},
include: 'rental,rental.rental-ratings'
});
}
});
Bookings template:
<h1>Your bookings</h1>
{{#each model as |booking|}}
{{booking-card booking=booking rating="??? what goes here???"}}
{{/each}}
Easiest way to achieve this, is to use the ember-composable-helpers.
Move the sessionAccount service into the controller. In your template you can just use the filter-by helper:
{{#each model as |booking|}}
{{booking-card booking=booking rating=(get (filter-by "user" sessionAccount.user booking.rental.rentalRatings) "firstObject")}}
{{/each}}
I am trying to learn EmberJS and restify. I have get method API with following response :
{"products":[{"id":1,"name":"lappy1"},{"id":2,"name":"lappy2"}]}
This response I am getting in my browser's network log.
My product route is like :
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return {
products :this.get('store').findAll('product')
};
}
});
My product.hbs is :
<div>
<div class="row">
<div class="col-md-4"><b>id</b></div>
<div class="col-md-4"><b>Name</b></div>
</div>
{{#each model.products as |product|}}
<div class="row">
<div class="col-md-4">{{product.id}}</div>
<div class="col-md-4">{{product.name}}</div>
</div>
{{/each}}
</div>
My product model is :
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string')
});
There is no any error on log, but my page only shows header part i.e
<div class="col-md-4"><b>id</b></div>
<div class="col-md-4"><b>Name</b></div>
which thing I am missing ?
Install Chrome Ember plugin and use Chrome for debugging.
I assume you are using the RESTAdapter?
Your Route's model hook returns an object, not a promise. This is a little odd, I would recommend using a Hash:
model() {
return Ember.RSVP.hash({
products: this.store.findAll('product')
});
}
Alternately, you could just return the result of calling the store:
model() {
return this.store.findAll('product');
}
But in this case, you would change your templates to just use model instead of model.products.
I have a very simple set up right now. I have a book model that has a name and author. I'm trying to create a simple form that will create a new book. For the author I'm using power select to load the authors from the author model. The form set up looks like this:
<form {{action "save" on="submit"}}>
{{input value=model.title placeholder="Title"}}<br>
{{#power-select class="select"
selected=model.author
options=authors
onchange=(action (mut model.author)) as |author|}}
{{author.name}}
{{/power-select}}
<input type="submit" value="Save">
</form>
However I'm having trouble setting up the route to get this working. So far no authors show up in the select, even though there are authors stored in my database. My route looks like this:
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.store.createRecord('book');
},
actions: {
save() {
this.modelFor(this.routeName).save();
}
},
store: Ember.inject.service(),
authors: Ember.computed({
get() {
return this.get('store').findAll('author');
}
}).readOnly()
});
First of all, how should I properly load data from the author model in the route for the books/new route? Secondly, should I be doing this in the route? From what I have read, and what people have told me, loading model data should be done in the route.
Move authors property to corresponding controller.
Also you don't need to add readonly.
So in controller :
authors: Ember.computed(function(){
return this.get('store').findAll('author');
})
And for loading model in route. Yes you should load that model which is to be a resource manipulating, in route. So now you're doing it right.
1) Using Ember.RSVP.hash inside route model hook
your route file-> I assume books/new.js
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return Ember.RSVP.hash({
newBook : this.store.createRecord('book'),
authors : this.store.findAll('author')
});
},
actions: {
save() {
this.modelFor(this.routeName).newBook.save();
}
}
});
and inside template you can access authors by using model.authors. and title by using model.newBook.title
<form {{action "save" on="submit"}}>
{{input value=model.newBook.title placeholder="Title"}}<br>
{{#power-select class="select"
selected=model.newBook.author
options=model.authors
onchange=(action (mut model.newBook.author)) as |author|}}
{{author.name}}
{{/power-select}}
<input type="submit" value="Save">
</form>
2) Like ebrahim suggested, you can have the below code in required controller,
authors: Ember.computed(function(){
return this.store.findAll('author');
})
3)As author model data is going to be shared data model for authors,books,books.new routes. so you can keep it in service and access it from all the required routes.
authors-service.js -> In service
import Ember from 'ember';
export default Ember.Service.extend({
store:Ember.inject.service(),
authors: undefined,
init(){
this._super(...arguments);
this.get('store').findAll('author', { reload: true }).then(function(results){
this.set('authors',results); //As this is going to be Ember.enumerables, you can iterate and get the data.
});
}
});
You can access authors from authors-service.js in any where by injecting it
authorsService:Ember.inject.service(). I guess in your case, you need to create controller books/new.js for books/new.hbs template,
books/new.js -> controller file
import Ember from 'ember';
export default Ember.Controller.extend({
authorsService:Ember.inject.service(),
authors: Ember.computed.alias('authorsService.authors');
});
Inside books/new.hbs template you can access authors property.
I'm trying to build a simple chat app using Ember CLI with a rails API backend, using simple-auth-devise. I am very new to Ember. I have the following setup:
A conversation model which has_many messages. Each message belongs_to a user.
A conversations/show route which loads a conversation and displays all messages
The problem I have is figuring out which messages were written by the current user. I can identify the current user in the route and pass this to the controller, but I'm not sure how to do something in the template which is conditional on this. Here is the code:
Route for conversations/show:
import Ember from 'ember';
export default Ember.Route.extend({
model: function(params) {
return this.store.find('conversation', params.conversation_id);
},
// Get the current user
setupController: function(controller, model){
this._super(controller, model);
var currentUser = this.get('session').get('currentUser');
controller.set("currentUser", currentUser);
}
});
Then in the template I want to do something like this:
{{#each message in messages}}
{{message.body}}
{{#if message.isByCurrentUser }}
Written by me!
{{/if}}
{{/each}}
I don't know how or where to define that message.isByCurrentUser method to use the currentUser variable defined in the route.
Many thanks in advance.
I would recommend you to separate message resource and let it have its own template and controller.
//messages.hbs
{{#each message in messages}}
{{render "message" message}}
{{/each}}
//message.hbs
{{message.body}}
{{#if isByCurrentUser }}
Written by me!
{{/if}}
//message controller
import Ember from 'ember';
export default Ember.Controller.extend({
currentUser: Ember.computed.alias('session.currentUser'),
isByCurrentUser: function() {
return this.get('model.creator.id') === this.get('currentUser.id');
}.property('model.creator', 'currentUser')
});
P.S: I assumed your message model has attribute named creator. change it due to your model
simple-auth injects session into controllers and routes so you don't have to set it explicitly.
I've got a model like this:
import DS from 'ember-data';
var Post = DS.Model.extend({
title: DS.attr('string'),
downloads: DS.hasMany('download')
});
export default Post;
and would like to show the downloads-section only when there is at least 1 or more downloads in the post.
I tried introducing a computed property in the Controller but can't access the model from there.
What else can I do?
EDIT: Here's the controller showing you what I was trying to do:
import Ember from 'ember';
export default Ember.ObjectController.extend({
hasDownloads: function(){
console.log(this.get('downloads')) // <- undefined
return true
}.property('model'),
})
EDIT2: The Object-controller above has no route since it's rendered using `{{render "post"}}. This is an example-template.
<ul class="posts">
{{#with model as post}}
{{render "post"}}
{{/with}}
</ul>
That would be its route:
import Ember from 'ember';
export default Ember.Route.extend({
model: function(params) {
return this.store.find('post', params).then(function(posts) {
return posts.get('firstObject');
});
}
});
Directly access the property on your controller using model.downloads:
import Ember from 'ember';
export default Ember.ObjectController.extend({
hasDownloads: function(){
console.log(this.get('model.downloads'))
return true
}.property('model.#each'),
})
Depending upon which version of Ember you are using, the proxying behavior of the controller will no longer work. Also, change the property so that it is updated when downloads are added and removed.