Suppose I have a graph (tree, whatever) and the structure in plain JS is like:
var trees = [{
name : 'my tree',
nodes : [
{
id : 0,
name : 'node 0',
type : 'fruit',
connectedTo : [1,2]
},{
id : 1,
name : 'node 1',
type : 'fruit',
connectedTo : [3,4]
},{
id : 2,
name : 'node 2',
type : 'fruit',
connectedTo : []
},{
id : 3,
name : 'node 3',
type : 'non-fruit',
connectedTo : []
},{
id : 4,
name : 'node 4',
type : 'non-fruit',
connectedTo : []
}
]
}]
Now in Ember, it would require me to have a Tree, Node and maybe a type model. No biggie. However, I need the data to be parsed for a tree graph. But when I access the data, it's like a chain of get() and then() calls (relationships are async between models).
this.get('nodes').then(function(nodes){
nodes.forEach(function(node){
node.get('type').then(function(type){
console.log(type.get('type')) // OMG
});
})
});
I was hoping to access them in dot-notation, something like tree.nodes[1].type. Is that possible in Ember? I have read several posts dealing with embedded data, and all they do is normalize external data to Ember models. I don't want that. What I want is to deal with embedded data inside the app.
You could use plainJS objects in Ember without the need to use Ember Data as in this example.
<script type="text/x-handlebars" data-template-name="index">
<ul>
{{model.name}}
{{#each item in model.nodes}}
<li>{{item.id}}</li>
{{#each connectedTo in item.connectedTo}}
{{connectedTo}}
{{/each}}
{{/each}}
</ul>
</script>
Once, you set your model data to your controller content, you could operate with your content as normal ember objects.
App.IndexRoute = Ember.Route.extend({
actions: {
changeValues: function(){
this.controller.set('content.name', 'changed');
this.controller.set('content.nodes.firstObject.id', 7);
}
},
model: function() {
return {
name : 'my tree',
nodes : [
{
id : 0,
name : 'node 0',
type : 'fruit',
connectedTo : [1,2]
},{
id : 1,
name : 'node 1',
type : 'fruit',
connectedTo : [3,4]
},{
id : 2,
name : 'node 2',
type : 'fruit',
connectedTo : []
},{
id : 3,
name : 'node 3',
type : 'non-fruit',
connectedTo : []
},{
id : 4,
name : 'node 4',
type : 'non-fruit',
connectedTo : []
}
]
};
}
});
Related
Hii here is my simple logical question
this is my reference array
referenceArray =[{name : "animal" , source :['duck', 'cat'], target:['water', 'ground']},
{name : "car" , source :['tata', 'kia'], target:['tiago', 'sector']},
{name : "bike" , source :['honda', 'hero'], target:['livo', 'xtream']}
]
this is i want to modify the source and target array with the above referenceArray array
originalArray =[{source : 'water' , target : 'hero'},
{source : 'tata' , target : 'ground'},
{source : 'livo' , target : 'kia'},
]
but i want the final output like this
originalArray =[{source : 'animal' , target : 'bike'},
{source : 'car' , target : 'animal'},
{source : 'bike' , target : 'car'},
]
can anyone help me out please that is soo appreciatable
You can simply build a Map of the reference array with each source and target elements keyed against the name, then map over the originalArray accessing the Map. Keep in mind this does nothing to avoid possible overlap of source and target arrays.
const referenceArray = [{ name: "animal", source: ['duck', 'cat'], target: ['water', 'ground'] }, { name: "car", source: ['tata', 'kia'], target: ['tiago', 'sector'] }, { name: "bike", source: ['honda', 'hero'], target: ['livo', 'xtream'] }];
const originalArray = [{ source: 'water', target: 'hero' }, { source: 'tata', target: 'ground' }, { source: 'livo', target: 'kia' },]
const referenceMap = new Map()
for (const { name, source, target } of referenceArray) {
for (const k of [...source, ...target]) {
referenceMap.set(k, name);
}
}
const result = originalArray.map(({ source, target }) => (
{
source: referenceMap.get(source),
target: referenceMap.get(target)
}
));
console.log(result)
I got an array with some elements and each element has some properties like name, id and children. Each element has children property and then sub children so on and so forth. This array is already there in our application. Now I want to update all of elements and sub elements of our array with a new property called "path". The "path" will be the key and its value will be the addition of its previous object's name. For example
let dataArray = [
{
name: 'Data',
id: 12,
path: 'Data',
children: [
{
name: 'Data Center',
id: 13,
path: 'Data/Data Center',
children: [
{
name: 'Data Management',
id: 13,
path: 'Data/Data Center/Data Managemet',
},
],
},
],
},
{
name: 'Machine',
id: 12,
path: 'Machine',
children: [
{
name: 'Machine Center',
id: 13,
path: 'Machine/Machine Center',
children: [
{
name: 'Machine Management',
id: 13,
path: 'Machine/Machine Center/Machine Managemet',
},
],
},
],
}
];
As you can see path property to all the elements. I want to make this happen programatically. For that, here is the piece of code I have written but I am not able to understand what need to need to be done to achieve. This piece of code adds path property to all the elements and sub elements but with name as path like above example. I want the addition of previous names which have been traversed.
addPathProperty(){
dataArray.forEach((element) =>{
element.path = element.name;
if(element.children.length > 0){
this.addPathProperty(element.children)
}
});
}
Here is the link Stackblitz. Any help will be appreciated. Thank you
I think this code should work:
const appendPath = (root = '') => (obj) => {
obj.path = root ? `${root}/${obj.name}` : obj.name
if (obj.children) {
obj.children.forEach(appendPath(obj.path))
}
}
dataArray.forEach(appendPath())
appendPath is a function that accepts a root, when this function is invoked, it will combine root and name and set this to object.path; After that, it will do the same for the object.children if they exists
i am trying to check my inner array id same as dispatched id, table example
{
_id :1,
name: sagar elias jacky
Amenities :[{ id: 100, title : hi },{ id: 101, title : hallo } ]
}
checking dispatched id exit or not using map,
return { ...state,
items : {...state.items,
Amenities : { ...state.items.Amenities
.map(x=> x._id === action.dispatchedID ? {...x,deleting: true} : x ) }}}
but it will return with non array Amenities, like
Amenities:
0: { id: 100, title : hi },
1: { id: 101, title : hallo }
i want this to
Amenities:Array(2)
0: { id: 100, title : hi },
1: { id: 101, title : hallo }
When you spread an array inside {}, it creates an object with indexes of array as keys
const array = [{a:1}, {a:2}]
console.log({...array})
So, change
Amenities : { ...state.items.Amenities
.map(x=> x._id === action.dispatchedID ? {...x,deleting: true} : x ) }
to:
Amenities : [ ...state.items.Amenities
.map(x=> x._id === action.dispatchedID ? {...x,deleting: true} : x ) ]
I have an object like this :
Object
section : array (1)
0 : {id : 1, name: 'foo'}
unit : array(2)
0 : {id : 1, name: 'bar'}
1 : {id : 2, name: 'bar2'}
but how to detect if the object has a section key or not ?
my code like this :
$.each(data, function(key,row){
if (row.section) {
$.each(row.section, function(key, val){
$('.select-section').append("<option value='"+val.id+"'>"+val.name+"</option>");
});
}else{
$('.select-section').html("<option value='-'>-</option>");
}
});
but my when i have an object like that above, the results is just replace the section option value with else condition (-)
i create this because sometimes an Object doesn't have a section key, so i create a default option when the section key is unavailable
any help will be appreciated
I changed two things in your JS code:
if (key=="section") instead of if (row.section) to check if the key is section or not;
$('.select-section').append instead of $('.select-section').html cause whatever you could append the html() function will replace the whole html inside the select tag to <option value='-'>-</option>, then you'll never have other option then this one.
Please check this demo for a better understanding:
var object={
section : {
0 : {id : 1, name: 'foo'}
},
unit : {
0 : {id : 1, name: 'bar'},
1 : {id : 2, name: 'bar2'}
}
};
$.each(object, function(key,row){
if (key=="section") {
$.each(row, function(key, val){
var opt="<option value='"+val.id+"'>"+val.name+"</option>";
$(".select-section").append(opt);
});
}else{
$('.select-section').append("<option value='-'>-</option>");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="select-section"></select>
This solution still not perfect because I believe that if you'll have another key that is not section the code above will append one more the selection tag with -;
var object={
section : {
0 : {id : 1, name: 'foo'}
},
unit : {
0 : {id : 1, name: 'bar'},
1 : {id : 2, name: 'bar2'}
},
unit2 : {
0 : {id : 1, name: 'bar'},
1 : {id : 2, name: 'bar2'}
}
};
$.each(object, function(key,row){
if (key=="section") {
$.each(row, function(key, val){
var opt="<option value='"+val.id+"'>"+val.name+"</option>";
$(".select-section").append(opt);
});
}else{
$('.select-section').append("<option value='-'>-</option>");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="select-section"></select>
So I suggest that you append the select tag at the beginning, then there is no need to check if the key is not section. Here is another and better demo :
var object={
section : {
0 : {id : 1, name: 'foo'}
},
unit : {
0 : {id : 1, name: 'bar'},
1 : {id : 2, name: 'bar2'}
},
unit2 : {
0 : {id : 1, name: 'bar'},
1 : {id : 2, name: 'bar2'}
}
};
$('.select-section').append("<option value='-'>-</option>");//APPEND It HERE
$.each(object, function(key,row){
if (key=="section") {
$.each(row, function(key, val){
var opt="<option value='"+val.id+"'>"+val.name+"</option>";
$(".select-section").append(opt);
});
}//NO NEED TO CHECK If It's NOT "SECTION"
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="select-section"></select>
you can just do:
var data = {
section: [{
id: 1,
name: 'foo'
}],
unit: [{
id: 1,
name: 'bar'
}, {
id: 2,
name: 'bar2'
}]
};
if (data.section && data.section.length > 0) {
$.each(data.section, function(key, val){
$('.select-section').append("<option value='"+val.id+"'>"+val.name+"</option>");
});
} else {
$('.select-section').html("<option value='-'>-</option>");
}
plnkr: http://embed.plnkr.co/dxzbHir4x0RjQwQAfse1/
I am using a combination of highcharts and knockoutjs to feed data into my chart.
I have 4 massive arrays of data that need to be fed into my highchart upon a click event. I showed the data arrays empty here due to their huge size. Currently it returns an error like: Uncaught TypeError: Cannot read property 'metric' of undefined
My question is how do I access the areas.metric.data and parse it into my chart?
here is my (non) working fiddle:
http://jsfiddle.net/whiteb0x/BG8Qe/18/
function MetricsViewModel(areas) {
var self = this;
self.areas = [ // data structure
{
name: 'Game',
metrics: [{name : 'metric1', id : 'usdeur', data : []}, {name : 'metric2', id : 'msft', data : []}]
},
{
name: 'Player',
metrics: [{name : 'metric1', id : 'msft', data : []}, {name : 'metric2', id : 'msft', data : []}]
},
{
name: 'Social',
metrics: [{name : 'metric1', id : 'googl', data : [] }, {name : 'metric2', id : 'msft', data : []}]
}
];
series: [{ // default series
id: 'adbe',
data: ADBE
}]
}, function(chart){
var data = areas.metric.data; // corresponds to my object above ^^^
self.updateChart = function(metric) {
var id = this.id,
series = chart.get(id);
if(!series){
chart.addSeries({
id: id,
data: data
});
} else {
series.remove();
}
console.log(metric);
}
});
I'm not sure I understand you correctly, but according your code, this function declared in the ViewModel scope:
function(chart){
so you can access access both areas array and you observable metrics array like this:
var data = self.areas[0].metrics;
or observable metrics array like
self.metrics()
in any case, at the line where you have troubles, you are in ViewModel scope and can access whatever you want in it by this or self