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.
Related
For example we have the following input component:
<input type="text" v-model="example.modules.report.description.title"></input>
Full source
I don't want to define in data following object:
example: {
modules: {
report: {
description: {
title: ""
}
}
}
}
I anticipate that Vue.js will create that structure itself (just like Angular.js), but it doesn't do it.
Is there any way to solve this problem?
the data() method is a factory that initializes the model on which the component is bound.
The docs explains clearly how is supposed to make it work
You should declare the initial value on the JavaScript side, inside the data option of your component.
vuejs docs
If your model is so complex to require all these nested compositions maybe you have to be fine with it or design a different data model.......or create your model with your own factory
export default {
data : example()
}
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.
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.
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
I am confused and in a fix with regards to controllers and components detecting changes in models. According to the Ember Official Documentation --
"By default, the value returned from your model hook will be assigned to the model property of the associated controller. For example, if your App.PostsRoute returns an object from its model hook, that object will be set as the model property of the App.PostsController."
Therefore, shouldn't the controller update when the model changes in the route or, asynchronously by way of an external function?
App.IndexRoute = Ember.Route.extend({
model: function(){
App.set('localStore', this.get('store'));
App.localStore.createRecord('stats', {'name': 'cde'});
return this.store.find("stats");
}
});
App.IndexController = Ember.Controller.extend({
modelObs: function() {
// Never triggered!
console.log("CONTROLLER: model updated!");
}.property('model')
});
// Component with the controller's model property passed to it as localModel
// in the template
App.NewCompComponent = Ember.Component.extend({
localModel: null,
modelObs: function() {
console.log("COMPONENT: Model updated!");
}.property('localModel')
Here's a Jsbin that illustrates the problem - http://jsbin.com/tavis/3/edit
Is there anything I might be doing wrong? How to get a component detect a change in a passed model from the controller, and similarly how to get the controller detect a change in the route's model? Perhaps I'm missing a thing or two -- pointers are appreciated! Thanks
Computed properties aren't evaluated unless they are used. They are lazily evaluated.
Using either of those properties will cause them to be evaluated and your logs will occur.
http://jsbin.com/suheroya/1/edit
Additionally it's important to know that the model itself isn't changing, so that computed property won't be called over and over. Properties on the model are changing, and if you want the computed property to be called over and over you'll need to watch those properties.