Ember.js: accessing computed alias from component's javascript - javascript

I currently have a model that contains a computed alias, as follows:
model: DS.belongsTo('device-model'),
manufacturerName: Ember.computed.alias('model.manufacturer.name')
I then have a component that is invoked as follows:
{{my-component model=model}}
Now, in the component's Handlebars template, I can easily access the computed property with {{model.manufacturerName}}, however in my-component.js I am having trouble getting it to work. I have tried with:
console.log(this.get('model').get('manufacturerName'))
However, the output is undefined. So far, the only way I can get the manufacturer name from my-component.js is:
this.get('model').get('model')
.then((model) =>{
return model.get('manufacturer')
})
.then((manufacturer) => {
console.log(manufacturer.get('name'))
})
So, I'm wondering what is the Handlebars template doing that I can't do in its javascript counterpart? It seems like the Handlebars template is following through the promise, whereas I have to do it manually when it comes to the component's javascript.
Thank you!

I think the issue is because of your belongsTo relationship. since { async: true} is the default value for relationships in Ember. so it only fetch the related entities when you actually request them. which means your model is not loaded which means your manufacturerName is not loaded since it is an alias of model.manufacturerName.name.

Related

Ember.js computed property to return model ID array?

Updated: 11:36PST 07 Dec 2017
All I'm trying to do is create an array containing a list of current ID's in the model to use in a child component, but somehow seem to be missing something obvious. If it is relevant, I am using Ember 2.17.0 with Ember Data 2.17.0 as well.
The route returns an array of models very similar to a findAll, but modified to work with a REST endpoint I do not have any control over. I need an array of the id's from the model to use in a component embedded in the route. Based on feedback, I have attempted to implement this in both the route and the controller.
In the controller, I'm trying it this way.
searchIdArrayC: computed('model', () => {
return this.get('model').map((record) => record.get('reachId'));
})
..and in the route I'm trying it this way.
searchIdArrayR: computed('model', () => {
return this.modelFor('reaches').map((record) => record.get('reachId'));
});
When I look at it in the Chrome Ember Inspector, for both the route and controller it is telling me Error while computing: searchIdArrayR or Error while computing: searchIdArrayC.
Just to try and do some testing, I sent both the route and the controller to the console. With both the route and controller, the aforementioned methods are working, so I am really confused.
Thank you in advance for any help or guidance you may be able to offer.
In route file, model is a function, but you are treating it like model property which is available in the corresponding controller.
If you can move searchIdArray computed property to corresponding controller then that should work.

Ember.js: getting model relationships from component's javascript

I am building a component, and I have noticed a behaviour that seems very odd to me. My component is invoked as follows:
{{my-component model=model}}
My model contains a relationship as follows:
type: DS.belongsTo('type')
Now, in my-component.js, if I log to console this.get('model.type.name') (or this.get('model').get('type').get('name')), I get undefined. However, if in my-component.hbs I insert {{model.type.name}}, the value is displayed correctly.
I don't really understand this behaviour: how can I access a model's relationship from within a component's javascript just like I do in the component's Handlebars template?
Thanks!
In ember-data, relationship is treated as Promise so you should use then for the result.
this.get('model').get('type').then((result) =>{
console.log(' Name ', result.get('name'));
});
Refer:
https://guides.emberjs.com/v2.14.0/models/relationships/#toc_relationships-as-promises

Ember.js: How to access a model's attributes inside Javascript code

In Ember.js while using ember-data, I can access a model's attributes like this when in a .hbs template:
{{#each model as |person|}}
Welcome, {{person.firstName}} {{person.lastName}}!
{{/each}}
I tried accessing these values in Javascript code (be it inside a controller or a component) using the following methods:
// Method 1
if (person.firstName === 'Jack') {
// Do something when the first name is Jack
}
// Method 2
if (person.get('firstName') === 'Jack') {
// Do something when the first name is Jack
}
But none of these work to get any attributes of the current model. The only value I can get this way is the id of the current model instance.
I have looked far and wide for a solution to this problem and found nothing, so I ask this question:
Is it possible to access the attributes of a model instance inside Javascript code while using Ember.js and ember-data? If so, how can this be done? If not, why can't I do that?
For reference, here is my current Ember.js setup:
DEBUG: Ember : 2.5.1
DEBUG: Ember Data : 2.5.3
DEBUG: jQuery : 2.2.4
DEBUG: Ember Simple Auth : 1.1.0
When you have an object that you're passing into a component, it becomes a property of the component. So you need to get that object via the component's property before accessing any properties on the model object itself.
Assuming you're passing the object into a component like this:
{{person-profile person=person}}
Either of these should work:
// Method 3
if (this.get('person').get('firstName') === 'Jack') {
// Do something when the first name is Jack
}
// Method 4
if (this.get('person.firstName') === 'Jack') {
// Do something when the first name is Jack
}

Ember js 2.0 passing computed property from controller to component

I am using Ember 2.3.
Like the title says I am trying to pass a computed property from my controller to my component. I don't know what I am doing incorrectly but it is not working for me. This is what I am doing:
In my controller:
import Ember from 'ember';
export default Ember.Controller.extend({
someProperty: 'someValue',
myComputedProperty: Ember.computed('someProperty', function(){
return {property: this.get('someProperty')};
})
});
My component:
export default Ember.Component.extend({
myProperty: {}
});
In my template:
{{my-component myProperty=myComputedProperty}}
What I am seeing is that my myProperty in my-component is always set to {}. It never gets the value I hand in the template. Note I've also tried just defining a property as a string literal on my controller and handing that in and it is not recognized either. Also of note is that I did originally try defining the computed property in my route but I found the only way I could access it was if it was defined in the model hook itself, like:
model(params) {
return {
myComputedProperty: Ember.computed()...........
};
}
But this wasn't working for me because I needed values from the controller that were not available when the model hook was called.
I don't know what I am doing wrong here. I'm sure it's something simple, but I am running out of ideas. Could anyone tell me what I am doing wrong here? Is passing a computed property from a controller to a component bad practice in any way? Any advice would be appreciated. Thanks much!
Passing computed properties into a component from a controller is fine.
The code you have should be working. The one question/change is: Do you need to be returning a nested object in you controller's computed property? {property: this.get('someProperty')}`
If so, then you need to call .property on it in your component in order to access the controller's someProperty value.
my-component/template.hbs
{{myProperty.property}}
Here's an ember-twiddle demonstrating the code working.

Accessing asynchronously loaded object based on relations in Ember

I have a trouble with asynchronously loaded models in Ember. I thought I have already understood the whole "background Ember magic", but I haven't.
I have two models, let's say foo and boo with these properties:
foo: category: DS.belongsTo("boo", { async: true })
boo color: DS.attr("string")
In my route, I load all foos:
model: function(params) {
return this.store.findAll("task", "");
},
than in my template I render a component: {{my-component model=model}}. In the component's code I need to transform the model into another form, so I have:
final_data: function() {
this.get("model").forEach(function(node) {
console.log(node.get("category"));
});
return {};
}.property("model"),
When I try to access the "category" in the model, my code crashes:
EmberError#http://localhost:4200/assets/vendor.js:25705:15
ember$data$lib$adapters$errors$$AdapterError#http://localhost:4200/assets/vendor.js:69218:7
ember$data$lib$adapters$rest$adapter$$RestAdapter<.handleResponse#http://localhost:4200/assets/vendor.js:70383:16
ember$data$lib$adapters$rest$adapter$$RestAdapter<.ajax/</hash.error#http://localhost:4200/assets/vendor.js:70473:25
jQuery.Callbacks/fire#http://localhost:4200/assets/vendor.js:3350:10
jQuery.Callbacks/self.fireWith#http://localhost:4200/assets/vendor.js:3462:7
done#http://localhost:4200/assets/vendor.js:9518:1
.send/callback#http://localhost:4200/assets/vendor.js:9920:8
It seems to me, like the Ember didn't load the boos. How should I access them right to make Ember load them?
It's trying to load category, but the adapter is encountering some error. Can't tell what from your example.
Check your network tab.
When you access an async association from a template, Ember knows what to do. From code, such as your component's logic, Ember has no idea it needs to retrieve the association until you try to get it. The get will trigger the load, but will return a promise. You can do this:
get_final_data: function() {
Ember.RSVP.Promise.all(this.get("model") . map(node => node.get('category'))
.then(vals => this.set('final_data', vals));
}
As I'm sure you can see, this creates an array of promises for each node's category, calls Promise.all to wait for them all to complete, then stores the result into the final_data property.
Note, this is not a computed property; it's a function/method which must be called at some point, perhaps in afterModel.

Categories