I have Ember.Object which is being used as a basic key/value dictionary. The names of the keys are dynamic and what I'd like to be able do is iterate over these properties. Seems like this should be easy but google searches and my collective head scratching doesn't seem to point to the obvious answer I was expecting.
For the following psuedo code:
App.MyObject = Ember.Object.extend({
randomComputedProperty: function() {
return "foobar";
}
}
$object = new MyObject.create(someBigAndUnpredictableNameValueHash);
My ideal solution would solve for this code would allow me to quickly discern:
object
hasobject
hasAnyway have any ideas?
----- UPDATE -----
To be a little more explicit about my precise use case. The fictional MyObject
is actually a property that comes in from one my models:
App.MyModel = DS.Model.extend({
prop1: DS.attr('string'),
prop2: DS.attr('number'),
prop3: DS.attr('my-object')
}
Where a Transform object is setup to handle serialization/deserialization:
App.MyObjectTransform = DS.Trnasform.extend({
deserialize: function(serialized) {
return App.MyObject.create(serialized)
},
deserialize: function(deserialized) {
return deserialized;
}
}
This way when I'm working with MyModel
in a handlebars template I can do something like:
{{prop1}}
{{prop2}}
{{#each prop3}}
{{key}} = {{value}}
{{/each}}
In Ember v2.0.0-beta.1 you can use {{each-in}}
helper, which lets you to iterate over object keys and their values in your templates.
For example, sample object:
App.MyObject = Ember.Object.extend({
randomComputedProperty() {
return 'foobar';
}
});
Instantiated this way:
let $object = App.MyObject.create({
prop1: 'value1',
prop2: 'value2',
prop3: ['element1', 'element2']
});
And iterated over in template using {{each-in}}
helper:
{{#each-in $object as |key value|}}
`{{key}}`:`{{value}}`
{{/each-in}}
Produces following results:
`prop1`:`value1`
`prop2`:`value2`
`prop3`:`element1,element2`
JSBin demonstrating this.
It's worth to mention that using {{each-in}}
helper:
is a one time snapshot look at the object, it will not observe properties being added/removed/changed.
Thanks @Kingpin2k for pointing this out. Demo, note that update to prop1
isn't reflected in the DOM.
Here are some ideas.
Object's Keys method 1
You can iterate over the properties and filter out the keys from the prototype chain (using the hasOwnProperty()
method):
var obj = App.MyObject.create({stuff: "stuff!"});
var objKeys = []
for(var key in obj) {
if(obj.hasOwnProperty(key)){
objKeys.push(key);
}
}
console.log(objKeys); // ['stuff']
Object's Keys method 2
On newer browsers you can directly get an array of the object's properties using the Object.keys()
method:
console.log(Object.keys(obj)); // ['stuff']
Ember.Object's computed properties
Ember provides a way to iterate over the computed properties of a class using the eachComputedProperty()
method
App.MyObject.eachComputedProperty(function(name, meta){
console.log(name, meta); // randomComputedProperty
});
JSBin example demonstrating these methods
Update
You could have a computed property on your model that re-arranges the MyObject
's data into an array which can then be displayed by handlebars:
App.MyModel = DS.Model.extend({
prop1: DS.attr('string'),
prop2: DS.attr('number'),
prop3: DS.attr('my-object'),
prop3PropertyArray: function(){
var prop3,
propertyArray = [];
prop3 = this.get('prop3');
for(var key in prop3) {
if(prop3.hasOwnProperty(key) && key !== "toString"){
propertyArray.push({key: key, value: prop3.get(key)});
}
}
return propertyArray;
}.property('prop3')
});
If prop3
contained:
prop3: App.MyObject.create({
stuff: "stuff!",
anotherRandomKey: "more value here"
})
then prop3PropertyArray
would be:
[
{
key: "stuff",
value: "stuff!"
},
{
key: "anotherRandomKey",
value: "more value here"
}
]
which can then be displayed in handlebars using an {{#each}}..{{/each}}
helper:
{{#each item in prop3PropertyArray}}
{{item.key}} = {{item.value}}<br>
{{/each}}
Updated JSBin example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With