I am getting an object with several nested objects back from a collection.fetch() call. Is there a way to parse these sub-objects and pass them into the collection as individual models?
Here is an example of the data I am getting back. I'd like to pass this into the collection as 3 models when it is fetched from the server.
Here is a fiddle to what I am trying but I am not sure of the best way to go about this: http://jsfiddle.net/L8ov7oo5/
Data from server:
{
"slides": {
"date": "August 21, 2014",
"Author": "Luke Skywalker",
"slide1": {
"content": {
"headline": "headline 1",
"desc": "description for slide 1",
"image": [
{
"url": "http://placekitten.com/100/100",
"type": "thumbnail",
"alt": "imageofakitten"
}
]
}
},
"slide2": {
"content": {
"headline": "headline2",
"desc": "descriptionforslide2",
"image": [
{
"url": "http: //placekitten.com/125/125",
"type": "thumbnail",
"alt": "imageofakitten"
}
]
}
},
"slide3": {
"content": {
"headline": "headline3",
"desc": "descriptionforslide3",
"image": [
{
"url": "http: //placekitten.com/150/150",
"type": "thumbnail",
"alt": "imageofakitten"
}
]
}
}
}
}
Example of model I'd like to pass to the collection:
{
"slide1": {
"content": {
"headline": "headline 1",
"desc": "description for slide 1",
"image": [
{
"url": "http://placekitten.com/100/100",
"type": "thumbnail",
"alt": "imageofakitten"
}
]
}
}
}
Here is my code, but when I log the results of the collection.fetch() I don't see 3 models in the collection.
var MyModel = Backbone.Model.extend({});
var MyCollection = Backbone.Collection.extend({
model: MyModel,
url: 'https://api.mongolab.com/api/1/databases/parse-test/collections/parse-test-collection?apiKey=x5akja343lqkja',
parse: function (response) {
console.log('response', response);
for (var prop in response[0].slides) {
if ( response[0].slides.hasOwnProperty(prop) ) {
// Try to add an object as a 'model' to the 'collection'
this.add( response[0].slides[prop] );
}
}
return response;
}
});
var myCollection = new MyCollection();
myCollection.fetch().done(function () {
// Expecting to see 3 models in this collection but I am not.
console.log(myCollection);
});
simply you can remove the properties date and Author and return the slides
parse: function (response) {
//console.log('response', response[0]['slides']);
delete response[0]['slides'].date;
delete response[0]['slides'].Author;
var temp = [];
$.each( response[0]['slides'], function(index, val) {
temp.push(val);
});
return temp;
}
DEMO
The parse call for your collection should return an array. Inside your for-in loop, add each of the objects you want to an array and return the array from parse when you're done.
var obj = response[0].slides,
returnList = [];
for (var prop in obj) {
if (obj.hasOwnProperty(prop) && prop !== 'date' && prop !== 'Author') {
returnList.push(obj[prop]);
}
}
return returnList;
here's a jsfiddle to demonstrate.
EDIT: here's another jsfiddle to demonstrate using _.map() instead of a for-in loop.
var obj = response[0].slides;
delete obj.date;
delete obj.Author;
return _.map(obj, function (value, key) {
return obj[key];
});
Related
Having the following nested array of objects:
[
{
"items": [
{
"name": "See data",
"href": "/data",
},
{
"name": "Account",
"href": "/account",
"icon": {}
}
]
},
{
"items": [
{
"name": "name",
"href": "/name",
"icon": {}
},
{
"name": "My Rooms",
"href": "/rooms",
"icon": {}
}
]
},
{
"items": [
{
"name": "user",
"href": "/user",
"icon": {}
}
]
}
]
How it's possible to remove an inside object by name?
For example to remove the object with name "Account"?
A solution that works is delete myData[0].items[1]; but it's kind of hardcoded.
Also tried like:
myData[0].items = myData[0].items.filter(function (item) {
return item.name !== 'Account';
});
You can use splice to change the original array in-place and findIndex to find the index of the item to remove.
for (const {items} of data) {
const i = items.findIndex(({name}) => name === 'Account');
if (i > -1) items.splice(i, 1);
}
This question already has answers here:
What is easy way to convert object in array Angular JS?
(3 answers)
Closed 6 years ago.
Here is my sample json , i am getting my json obj from firebase i have to convert the list in to array to bind in html trough ng-repeat.
my Json object is
{
"cats1": {
"Name": "cricket",
"imgUrl": "some url",
"list1": {
"bat": {
"Name": "bat",
"imgUrl": "some url",
"price": "$100"
},
"pads": {
"displayName": "pads",
"imgUrl": "some url",
"price": "$50"
}
}
},
"cats2": {
"Name": "football",
"imgUrl": "some url"
}
}
this is how i required
this is the array structure i required , when i add the new list it must store uniquely in cricket category.
[
{
"Name": "cricket",
"imgUrl": "some url",
"list1": [
{
"Name": "bat",
"imgUrl": "some url",
"price": "$100"
},
{
"displayName": "pads",
"imgUrl": "some url",
"price": "$50"
}
]
},
{
"Name": "football",
"imgUrl": "some url"
}
]
i am new to angular any one please help me to figure out this problem
Use Object.keys and pass them on to Array.prototype.map to create the array that you want - see demo below:
var object={cats1:{Name:"cricket",imgUrl:"some url",list1:{bat:{Name:"bat",imgUrl:"some url",price:"$100"},pads:{displayName:"pads",imgUrl:"some url",price:"$50"}}},cats2:{Name:"football",imgUrl:"some url"}};
var result = Object.keys(object).map(e=>object[e]);
console.log(result);
.as-console-wrapper{top:0;max-height:100%!important;}
EDIT:
Correcting the solution to make list1 an array:
var object={cats1:{Name:"cricket",imgUrl:"some url",list1:{bat:{Name:"bat",imgUrl:"some url",price:"$100"},pads:{displayName:"pads",imgUrl:"some url",price:"$50"}}},cats2:{Name:"football",imgUrl:"some url"}};
var result = Object.keys(object).map(function(e){
Object.keys(object[e]).forEach(function(k){
if(typeof object[e][k] == "object") {
object[e][k] = Object.keys(object[e][k]).map(function(l){
return object[e][k][l];
});
}
});
return object[e];
});
console.log(result);
.as-console-wrapper{top:0;max-height:100%!important;}
You can recursion but do note this can cause freeze for big objects and can also lead to Maximum Call Stack exceeded
Logic
Loop over object and check if all entries are objects.
If yes, then a simple Object.keys(obj).map(x=>obj[x]) will do.
If not, then you will have to copy individual values and if object, then again loop in it for inner objects. A simple way is to loop on every key and if type is not object, just return value.
function ObjectToArray(obj) {
if (typeof(obj) === 'object') {
var keys = Object.keys(obj);
var allObjects = keys.every(x => typeof(obj[x]) === 'object');
if (allObjects) {
return keys.map(x => ObjectToArray(obj[x]));
} else {
var o = {};
keys.forEach(x => {
o[x] = ObjectToArray(obj[x])
});
return o;
}
} else {
return obj;
}
}
var d={cats1:{Name:"cricket",imgUrl:"some url",list1:{bat:{Name:"bat",imgUrl:"some url",price:"$100"},pads:{displayName:"pads",imgUrl:"some url",price:"$50"}}},cats2:{Name:"football",imgUrl:"some url"}};
console.log(ObjectToArray(d))
You could do something like this, by iterating over the input object keys and stripping out the keys.
var app = angular.module("sampleApp", []);
app.controller("sampleController", ["$scope",
function($scope) {
$scope.result = {
"cats1": {
"Name": "cricket",
"imgUrl": "some url",
"list1": {
"bat": {
"Name": "bat",
"imgUrl": "some url",
"price": "$100"
},
"pads": {
"displayName": "pads",
"imgUrl": "some url",
"price": "$50"
}
}
},
"cats2": {
"Name": "football",
"imgUrl": "some url"
}
};
$scope.format = Object.keys($scope.result).map((key) => $scope.result[key])
}
]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<div ng-app="sampleApp">
<div ng-controller="sampleController">
<div>Formatted</div>
<pre>{{format | json}}</pre>
</div>
</div>
I'm working on Bootstrap calendar and I've tried to make my array looks like this:
{
"success": 1,
"result": [
{
"id": "293",
"title": "This is warning class event with very long title to check how it fits to evet in day view",
"url": "http://www.example.com/",
"class": "event-warning",
"start": "1362938400000",
"end": "1363197686300"
},
{
"id": "256",
"title": "Event that ends on timeline",
"url": "http://www.example.com/",
"class": "event-warning",
"start": "1363155300000",
"end": "1363227600000"
},
{
"id": "276",
"title": "Short day event",
"url": "http://www.example.com/",
"class": "event-success",
"start": "1363245600000",
"end": "1363252200000"
},
{
"id": "294",
"title": "This is information class ",
"url": "http://www.example.com/",
"class": "event-info",
"start": "1363111200000",
"end": "1363284086400"
}
] }
But I've tried and got something like this:
[
{
"success":1
},
{
"result":[
{
"id":"1",
"title":"dev",
"url":"www.example.com",
"class":"event-success",
"start":"0",
"end":"0"
},
{
"id":"2",
"title":"Holiday",
"url":"www.example.com",
"class":"event-success",
"start":"0",
"end":"0"
},
{
"id":"3",
"title":"Coding...",
"url":"www.example.com",
"class":"event-success",
"start":"0",
"end":"0"
},
{
"id":"4",
"title":"data",
"url":"www.example.com",
"class":"event-success",
"start":"0",
"end":"0"
}
]
}
]
and my code to create those mess are
var result = [];
for(i=0; i<rows.length; i++) {
var result_single = {id:rows[i].uid, title:rows[i].name, url:"www.example.com", class:"event-success", start:rows[i].startdate, end:rows[i].enddate};
result.push(result_single);
}
var output = new Array();
output.push(data);
result = {result:result};
output.push(result);
console.log(JSON.stringify(output));
To be honest, I don't quite understand how array in js works. can somebody point out how did i go wrong?
Your expected result is an object which contains 2 properties, but you get an array which contains two objects. I think you want the first result which is object with two properties.
var result = [];
var rows = [1,2,3,4,5];
for(i=0; i<rows.length; i++) {
var result_single = {id:rows[i], title:rows[i], url:"www.example.com", class:"event-success", start:rows[i].startdate, end:rows[i].enddate};
result.push(result_single);
}
var output = {
success: 1,
result: result
}
console.log(JSON.stringify(output));
I have a nested JSON Object and i want to iterate that.
JSON Response
{
"specifications": {
"IP6": {
"name": "Devices",
"productSubType": "Device",
"productSpecificationType": "Phones"
}
},
"offers": {
"US-PRE-IPHONE-CASE": {
"path": "productDetails/IP6",
"familyData": {
"0": "Missing Family Level data Should be here"
},
"facets": [],
"type": [],
"offers": {
"US-PRE-HG-PH-IP6": {
"hashDigest": "cf23df2207d99a74fbe169e3eba035e633b65d94",
"offerName": "offerNameString",
"productName": "iPhone 6 Case Mate Naked Tough Case - Clear",
"productOfferings": {
"ratings": "4.5",
"noOfReviews": "2010"
},
"offerStatus": {},
"displayPriority": "100200",
"descriptions": {
"shortDescription": "Iphone Decription ",
"longDescription": "longDescriptionStri6 descriptionng",
"alternativeDescription": "alternativeDescriptionString",
"reprsentativeDescription": ""
},
"specifications": [
"someSpecificationId1"
],
"brand": "Apple",
"productType": "Device",
"productSubType": "Phone",
"offerType": "",
"offerSubType": "",
"compatibility": {},
"classification": [],
"images": {
"thumbanail": {
"imagePath": "http://s.tmocache.com/images/png/products/accessories/SUPM43270/SUPM43270-small.png"
}
},
"equipmentCharacteristics": {},
"offerVariants": {},
"type": "hard-good",
"offers": [],
"family": "IP6",
"pricePoints": {
"withServicePrice16GBNEW": {
"displayPriority": "1001",
"pricingMessage": "device price with service activation",
"price": "34.99",
"discounts": {}
}
},
"dynamicPricingData": {},
"inventoryData": {
"SKUGOLD16GBN": {
"availibility": "Pre-order now!",
"availableTimeline": ""
}
}
}
}
}
}
}
Now as you see there are nested JSON objects in this and I want the value of
productName
shortDescription
imagePath
availibility
What I have tried is
function change(){
var acc = response; //response is JSON Object mentioned above
var accArray = [];
var accArray1 = [];
for (var obj in acc.specifications){
accArray.push(obj);
}
alert(accArray[0]);
for (var obj in accArray[0].offers){
accArray1.push(obj);
}
alert(accArray1[0]);
}
I am able to get the first object the first alert output is
IP6
but when I am trying to iterarte the IP6 object in same way the output is
undefined
I want to fetch all the 4 values as I mentioned above and then put them in an array.
As Grundy pointed out in his comment, obj in your code is the key of properties/items in specifications object. That means 'obj' is just a string.
To get reference to the object, change your code as below:
for(var obj in acc.specifications){
accArray.push(acc.specifications[obj]);
}
For better readability change obj to key
You can use for..in loop and recursion.
function find(obj, fieldName){
if(Array.isArray(obj)){
for(var i=0, len=obj.length;i<len;i++){
var nested = find(obj[i],fieldName);
if(nested.isFind) return nested;
}
}else{
if(typeof obj !== "object") return {isFind:false};
for(var i in obj){
if(i === fieldName) return {isFind:true, value:obj[i]};
var nested = find(obj[i],fieldName);
if(nested.isFind) return nested;
}
}
return {isFind:false};
}
this function return object with field isFind for case when available value can be null or undefined
var obj = {
"specifications": {
"IP6": {
"name": "Devices",
"productSubType": "Device",
"productSpecificationType": "Phones"
}
},
"offers": {
"US-PRE-IPHONE-CASE": {
"path": "productDetails/IP6",
"familyData": {
"0": "Missing Family Level data Should be here"
},
"facets": [],
"type": [],
"offers": {
"US-PRE-HG-PH-IP6": {
"hashDigest": "cf23df2207d99a74fbe169e3eba035e633b65d94",
"offerName": "offerNameString",
"productName": "iPhone 6 Case Mate Naked Tough Case - Clear",
"productOfferings": {
"ratings": "4.5",
"noOfReviews": "2010"
},
"offerStatus": {},
"displayPriority": "100200",
"descriptions": {
"shortDescription": "Iphone Decription ",
"longDescription": "longDescriptionStri6 descriptionng",
"alternativeDescription": "alternativeDescriptionString",
"reprsentativeDescription": ""
},
"specifications": [
"someSpecificationId1"
],
"brand": "Apple",
"productType": "Device",
"productSubType": "Phone",
"offerType": "",
"offerSubType": "",
"compatibility": {},
"classification": [],
"images": {
"thumbanail": {
"imagePath": "http://s.tmocache.com/images/png/products/accessories/SUPM43270/SUPM43270-small.png"
}
},
"equipmentCharacteristics": {},
"offerVariants": {},
"type": "hard-good",
"offers": [],
"family": "IP6",
"pricePoints": {
"withServicePrice16GBNEW": {
"displayPriority": "1001",
"pricingMessage": "device price with service activation",
"price": "34.99",
"discounts": {}
}
},
"dynamicPricingData": {},
"inventoryData": {
"SKUGOLD16GBN": {
"availibility": "Pre-order now!",
"availableTimeline": ""
}
}
}
}
}
}
}
function find(obj, fieldName){
if(Array.isArray(obj)){
for(var i=0, len=obj.length;i<len;i++){
var nested = find(obj[i],fieldName);
if(nested.isFind) return nested;
}
}else{
if(typeof obj !== "object") return {isFind:false};
for(var i in obj){
if(i === fieldName) return {isFind:true, value:obj[i]};
var nested = find(obj[i],fieldName);
if(nested.isFind) return nested;
}
}
return {isFind:false};
}
var result = ['productName','shortDescription','imagePath','availibility'].map(function(el){ return find(obj,el).value});
document.getElementById('r').innerHTML = JSON.stringify(result,null,2);
<pre id='r'></pre>
Your json code is a complex data binding structure. It same like c# complex data binding. So you need to call the obj by through it call name.
for eg:
var data = {"ex":{"a":{"a1":"a1","a2":"a2"},"b":{"b1":"b1","b2":"b2"}}}
so data is a class and it includes "ex" object
data returns =>Object {ex: Object}
if you need to access "a" or "b" object means , you need to access through the"ex" object.
for eg:
data.ex.a => Object {a1: "a1", a2: "a2"}
in your code
for(var obj in acc.specifications){
accArray.push(obj);
}
obj only push 1st element of acc.sppectification object.
So please try this.
foreach(var obj acc.specification){
arr1.push(acc.specification[obj])
}
foreach (var obj acc.offers){
arr2.push(acc.offers[obj])
}
I have a simple Json and I need to filter the objects based on a name, In this example I have two movie titles "Paddington" and "Interstaller" and lets say I only want to filter out by name "Paddington" and set the $scope only to the first item "Paddington" item
{
"feed": {
"author": {
"name": {
"label": "iTunes Store"
},
"uri": {
"label": "http://www.apple.com/itunes/"
}
},
"entry": [
{
"im:name": {
"label": "Paddington"
},
"im:image": [
{
"label": "url1",
"attributes": {
"height": "60"
}
},
{
"label": "url2",
"attributes": {
"height": "60"
}
},
{
"label": "url3",
"attributes": {
"height": "170"
}
}
]
},
{
"im:name": {
"label": "Interstellar"
},"im:image": [
{
"label": "url4",
"attributes": {
"height": "60"
}
},
{
"label": "url5",
"attributes": {
"height": "60"
}
},
{
"label": "url6",
"attributes": {
"height": "170"
}
}
]
}
],
"updated": {
"label": "2015-04-18T11:29:36-07:00"
},
"rights": {
"label": "Copyright 2008 Apple Inc."
},
"title": {
"label": "iTunes Store: Top Movies"
}
}
My code
app.controller('movieController', function ($scope, $routeParams, movieService) {
$scope.filterData = function init(){
$scope.movies = movieService.get({id: 4403});// returns the json
var filtered = $filter('filter')($scope.movies.entry, function(value,index){
return value["im:name"].label.indexOf("The Sound")!=-1;
});
$scope.firstItem = filtered[0];
};
alert($scope.firstItem);
});
app.factory('movieService',function ($resource) {
return $resource('https://itunes.apple.com/us/rss/topmovies/limit=50/genre=:id/json', {id: '#id'});
});
The $filter service will let you fetch a filter function, there is a filter function called 'filter' that is built in. Documentation here:
https://docs.angularjs.org/api/ng/filter/filter
app.controller('movieController', function ($scope, $filter, $routeParams, movieService) {
alert($routeParams.movieID);
$scope.movies = movieService.get({id: 4403});// returns the json
$scope.movies.$promise.then(function(resp){
var filterFunc = $filter('filter');
var filtered = filterFunc($scope.movies.feed.entry, function(value,index){
return value["im:name"].label.indexOf($routeParams.movieID)!=-1;
});
$scope.firstItem = filtered[0]; // could put this in place of movies but it's confusing since you're re-using that name for the initial resource and this filtered item
});
function test() {
alert(movieService.get({id: 4403}).entry.summary.label);
};
$scope.movies.name = {}; // need to return Paddington
$scope.movies.url = {}; // need to return url3
});
app.factory('movieService',function ($resource) {
return $resource('https://itunes.apple.com/us/rss/topmovies/limit=50/genre=:id/json', {id: '#id'});
});
There isn't an AngularJS-specific solution to this problem, it's a generic JavaScript issue. You want to loop through each object in the JSON dictionary and then check the title.
Something like this:
data = {
'feed': {
'entry': [
{'im:name': 'Paddington'},
{'im:name': 'Interstellar'},
]
}
}
$scope.movies.name = null;
for (var i = 0; i < data.feed.entry.length; i += 1) {
var movie = data.feed.entry.entry[i];
if (movie['im:name'].indexOf('Paddington') !== -1) {
$scope.movies.name = movie.title;
break;
}
}
You can also use the angular.forEach function.