get JSON object from knockout observable array by objects id - javascript

I can't find anything but basic examples of ko.observablearrays that show arrays of simple strings. I have an observable array that holds a largish JSON object with a lot of properties. I need to get the one of the objects in the array based off on the id property in the array. I have this code to get the Id:
self.selectedOrgId.subscribe(function (currentOrgId) {
alert(currentOrgId);
}, self);
my observable array is populated via an ajax get request and looks something like this:
[
{"userGuid":"37ab100e-f97b-462a-b3f4-79b8fbe24831",
"orgId":1,
"orgName":
"company ltd",
"isHiring":true,
...snip...}
more...
]
How can I look into my array and get the object with the orgId that I have?

When you need to find a specific object based on its id you can use ko.utils.arrayFirst as follow :
var selectemItemID = '1';
var selectemItem = ko.utils.arrayFirst(this.items(), function(i) {
return i.orgId == selectemItemID;
});
But you can also create an computed property that returns the selected item based on the selected item id.
self.selectedItem = ko.computed({
read : function(){
return ko.utils.arrayFirst(this.items(), function(i) {
return this.selectedOrgId() == i.orgId;
});
},
owner : self
});

Related

revise deeply nested JSON array in DOM

I have an HTML page that contains a stringified JSON object. The object has this structure:
{
"x":{
"key1":[],
"key2":{},
"keyN":{},
"myKey":{
"randomID238492":{
"items":[
{ "value":"zzzz" },
{ "value":"aaaa" },
{ ...}
]
}
}
}
}
I want to replace this object with one in which the "items" array has been sorted. Here is what I will and won't know about the object:
"myKey" and "items" will always be the relevant object keys
"myKey" will contain only one random ID, and the "items" key will always be its first child
I won't know the order of "myKey" in the object.
I won't know the true randomID under which "items" nests.
Is there a clear, efficient way to replace this JSON object with one in which "items" has been sorted? Right now, I do it by using this jQuery function after the page has rendered:
$(function() {
var myData = $( "#myJSON_string" )[0]; // <script> node that contains the string
var myDataJSON = JSON.parse(myData.innerText); // JSON string
var myKeyJSON = myDataJSON["x"]["myKey"]; // object
var myArr = myKeyJSON[Object.keys(myKeyJSON)[0]]["items"]; // array to sort
// Now sort and revise. I'm leaving myCompare() out of the example for brevity
myKeyJSON[Object.keys(myKeyJSON)[0]]["items"] = myArr.sort(myCompare);
myDataJSON["x"]["myKey"] = myKeyJSON;
myDataJSON = JSON.stringify(myDataJSON);
myData.innerText = myDataJSON;
});
This approach works, but it seems rather labored. It might be better, for example, if I could revise the JSON object "in place" without parsing it and then re-stringifying it.
Many SO posts, like this one, speak to the general question of how to sort a JSON array. But I can't see that any speak to the specific question posed here.

.map JSON based on specific value

I am trying to call Javascript's .map() method on a backbone collection that contains a JSON that looks like this:
[
{"from":"houston","to":"austin"},
{"from":"omaha", "to":"kc"}
]
My backbone model looks like this:
var ChoiceModel = Backbone.Model.extend({});
var choiceModel = new ChoiceModel({
a:'from',
z:'omaha'
})
The problem is every JSON document I'm interested in has the Key "from" instead of the city I'm interested in. Below I am trying to filter all the JSONs with the "from" value of "omaha".
var aVar = this.model.get('a');
var zVar = this.model.get('z');
return this.collection.map(function(model){
return {
a: model.get(aVar[zVar])
};
Ideally I would be able to later call variable 'a' it would only return: {"from":"omaha", "to":"kc"}.
I've tried a few variations of the code above to no avail. How can I .map() on JSON values?

Access JSON object key/value where value is an array using underscorejs

I have a local JSON dataset (outlined below) and am trying to use the _.where method to retrieve specific values from within the dataset.
JSON File
"data": [{
"singles_ranking": [116],
"matches_lost": ["90"],
"singles_high_rank": [79],
"matches_won": ["170"],
"singles_ranking/_source": ["116"],
"year_matches_won": ["11"],
"name": ["Pfizenmaier Dinah"],
"gender": ["woman"],
"_resultNumber": 1,
},{etc},{etc}];
Currently I am trying to retrieve values from within the dataset like so:
var mappedPlayers = _.map(players,function(key,val){return key});
var filteredPlayers = _.where(mappedPlayers, {name:'Pfizenmaier Dinah'});
console.log(filteredPlayers);
This currently returns undefined. I am 90% sure that this is because the key values are stored within an array however, I am not sure how I can modify this _.where condition to actually make it return the text within the value attribute.
Any help would be greatly welcomed. Thank you for reading!
With ._where it is not possible, but you can use _.filter, like so
var where = {key: 'name', value: 'Pfizenmaier Dinah'};
var filteredPlayers = _.filter(players, function (el) {
// check if key exists in Object, check is value is Array, check if where.value exists in Array
return el[where.key] && _.isArray(el[where.key]) && _.indexOf(el[where.key], where.value) >= 0;
});
Example

Backbone collection filter with where and get array of objects

I have a json like this:
Constants
Contents(Array)
->Sections(Array)
-->sections.attribute1
->constants.attribute1
->constants.attribute2
Templates
I have filtered the json to get a collection of Contents with this code:
var viasModel = Backbone.Model.extend({});
var viasCollection = Backbone.Collection.extend({
model: viasModel,
url: TEMPLATES_SERVICE,
parse: function(data){
return data.contents.data;
},
initialize: function(){
this.fetch();
},
route: function(via){
return this.where({viaId: via});
}
});
Lets say i have filtered with the route function with where the collection.
How can i filter the Sections(Array) and get only the elements of the sections of the filtered collection?
Is it with a each of the returned value of route?
this.where({viaId: via});
Do i have to find how can i nest a collection? Any help will be appreciated.
--EDIT--
When I assign the variable to arr, i get an object with attributes.
attributes: Object
-name: 'test',
-sections: Array[9]
--0: Object
---itemId: 'inicio'
---content: Array[2]
--1: Object
---itemId: 'hola'
---content: Array[2]
I want to get the content Object of the itemId === 'inicio' of the sections Array.
I don't want to look bad, so if you could guide me or give me some help I'm ok.
Thank you.
Okay thanks for your comment, seems like this is basically about filtering an array, here is my proposal:
var arr = collectionGenerated.where(name: 'attribute');
var result = $.grep(arr, function(val) {
return val.itemId == 'attribute';
});
result being the array containing only what fits both filters.
-- EDIT --
i guess in your data structure it is
var result = $.grep(arr.sections, function(val) {
return val.itemId === 'inicio';
});

How to build a json object with a loop?

I'm trying to loop through a number of items, and create a json object. Each loop should be a new item on the object, but I'm having some issues doing it. It seems that only one set of items gets added, instead of multiple ones.
Here is my code:
jsonObj = {}
rows.each(function (index) {
jsonObj["id"] = $this.find('.elementOne').val();
jsonObj["name"] = $this.find('.elementTwo').text();
});
Here is what my json looks like:
{
id: "3"
name: "Stuff"
},
Here is what I am trying to do:
{
id: "1"
name: "Stuff"
},
{
id: "2"
name: "Stuff"
},
{
id: "3"
name: "Stuff"
}
There is no JSON here. Please don't confuse:
A JavaScript object (a data structure)
A JavaScript object literal (code to create such a data structure)
JSON (a data format based on a subset of object literal notation)
If you want an ordered list of objects (or any other kind of JavaScript data structure) then use an array. Arrays have a push method.
var myData = [];
rows.each(function (index) {
var obj = {
id: $this.find('.elementOne').val(),
name: $this.find('.elementTwo').text()
};
myData.push(obj);
});
You override the object instead of adding it a new value each iteration.
Fixed code using an array:
jsonObj = [];
rows.each(function(index) {
jsonObj.push({
'id': $this.find('.elementOne').val(),
'name': $this.find('.elementTwo').text()
});
});​
What you want is an array of objects. When you try to write the same property on the same object multiple times, it gets overwritten which is why you're seeing id and name contain values for the last iteration of the loop.
Although you haven't tagged the question with jQuery, it does look like jQuery, so here's a solution:
I've taken the liberty to change $this to this because $this seems to be referring to the same object in each iteration, which is now what you may want (methinks)
var myArray = rows.map(function() {
return {
id: $(this).find('.elementOne').val(),
name: $(this).find('.elementTwo').text()
};
});
You can do it like this with jquery. The function will expect form elements of type input. It will iterate over thr passed form and it will collect each input name and value and it will create a json object like
Exmple:
HTML
<form action="" method="post" id="myForm">
<input type="text" name="field1" value="I am value of field 1"/>
<input type="text" name="field2" value="I am value of field 2"/>
</form>
Javascript
function buildObject(form) {
var jsonObject = [],
tempObj = {};
$(form).find("input:not(input[type='submit'])").each(function() {
tempObj[$(this).attr("name")] = $(this).val();
});
jsonObject.push(tempObj);
return jsonObject[0];
}
buildObject($("#myForm"));
//Will produce
jsonObj = {
field1 : "I am value of field 1",
field2 : "I am value of field 2"
}
This is because you're merely overwriting the same properties of your object, id and name, each time. You need to be making a sub-object for each, then push it into the master object (which I've converted to array, since it's non-associative).
var jsonObj = []
rows.each(function (index) {
var temp_obj = {};
temp_obj["id"] = $this.find('.elementOne').val();
temp_obj["name"] = $this.find('.elementTwo').text();
jsonObj.push(temp_obj);
});
[EDIT] - as Mark Eirich's answer shows, the temp_obj is unnecessary - you could push an anonymous object instead, but I defined temp_obj just to make it crystal clear what's happening.
Also read Quentin's very good points re: common confusion between JavaScript objects and JSON.
var jsonObj = [];
rows.each(function(index) {
jsonObj.push({
id: $this.find('.elementOne').val(),
name: $this.find('.elementTwo').text()
});
});

Categories