set alias for `model` hook - ember.js

HELP
If there is a model hook in app/routes/post.js say
model() {
return this.store.query('post');
}
in template the returned promised is accessed using
{{#each model as |post|}}
...
{{/each}}
Is there any way to set alias for the model? Something like this in route or controller?
posts: alias('model')
So I can access the returned promise in the template as
{{#each posts as |post|}}
...
{{/each}}
Is this something which is already present or something that got missed from ember documentation?

you can create alias for model property in your controller,
import Controller from '#ember/controller';
import { alias } from '#ember/object/computed';
export default Controller.extend({
posts: alias('model')
})
or using setupController in your route,
export default Route.extend({
setupController(controller, model) {
controller.set('posts', model);
},
});
Reference:
alias api documentation - alias computed property
alias your model - alias-model-rule

Related

Fetching records and nested relations

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}}

Accessing a property from a service in a template

I have a user service that manages reading data from localstorage, it has a property that reads from the local storage a certain object property, the service is setup like so
import Ember from 'ember';
import LocalUser from 'bidr/models/user-local';
const {
computed: {
alias
}
} = Ember;
export default Ember.Service.extend({
localUser: LocalUser.create(),
user_id: alias('localUser.user.id'),
active_auction: alias('localUser.user.active_auction')
});
In my route.js file for my item route I inject the service like so
user: Ember.inject.service('user'),
And in the template I'm attempting to access it like so
{{user.active_auction}}
I was under the impression I could do that but is that not the case? Do I need to set a property on the item route that is equal to the service property to make this work?
If you don't want to create a controller for this template's scope, you can expose the service to the template by setting a property in the auto-generated controller via the route's setupController hook, like so:
// application/some-route.js
export default Route.extend({
user: service(),
setupController(controller, model) {
this._super(controller, model);
set(controller, 'user', get(this, user))
}
});

EmberJS access properties without model object

I've got my route setup like so
export default Ember.Route.extend({
model: function(params) {
return this.store.findRecord('organization', params.organization_id);
}
});
When I'm printing out the properties, I have to do this in my template.
{{ model.name }}
Is there anyway I can drop the model part so it's just name?
You can do it if you want, though it's not great practice. In the setupController hook,
setupController(controller, model) {
this._super(controller, model);
controller.set('name', model.get('name'));
}
It'll set a property on the controller so you can access it in the template as {{name}}

Ember identifying current user

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.

Only show part of template if there exists at least one child-object

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.