Olli Savolainen
Olli Savolainen

Reputation: 13

JSON and Angularjs

I'm trying to loop some products in JSON. I get many different kinds of JSON files and that's why I made form that I can just manually "patch" the file.

{ "product": [ { "@attributes": { "ID": "123456789" }, "name": "Name of the product"],...}

So I have two input fields in my form:

1. id="product_name" value="name"
2. id="product_id" value="['@attributes']['ID']"

I use ng-repeat to loop throug products. These work fine:

{{product}} //Product object
{{product.name}} //name of the product
{{product[value]}} //if value = name, name of the product

My problem is that I don't know how to get that ['@attribute']['ID'] from the product.

EDIT: I know that this will work:

{{product['@attributes']['ID']}}

but I need to change the value from form input.

EDIT: SOLUTION:

controller.getData = function(object, key) {
        var keys = [];
        var count = key.replace(/[^.]/g, '').length;
        if(count === 4){
            keys = key.split(".");
            return object[keys[0]][keys[1]][keys[2]][keys[3]][keys[4]];
        }else if(count === 3){
            keys = key.split(".");
            return object[keys[0]][keys[1]][keys[2]][keys[3]];
        }else if(count === 2){
            keys = key.split(".");
            return object[keys[0]][keys[1]][keys[2]];
        }else if(count === 1){
            keys = key.split(".");
            return object[keys[0]][keys[1]];
        }else{
            return object[key];
        }
    };

New problem:

{ "product": [ 
{ "@attributes": { "ID": "12345" }, 
"name": "productname", 
"price": "xx", 
"URL": "url", 
"images": { "image": "imgUrl" }, 
"description": {}, 
"categories": { 
"category": "Kesäale" }, 
"properties": { "property": [ 
{ "@attributes": { "name": "color" }, "value": "B25 Grisaille" }, 
{ "0": "\n", "@attributes": { "name": "size" } }, 
{ "@attributes": { "name": "currency" }, "value": "EUR" }, 
{ "@attributes": { "name": "brand" }, "value": "brandName" }, 
{ "@attributes": { "name": "fromPrice" }, "value": "xx" }, 
{ "@attributes": { "name": "manufacturer" }, "value": "xx" }, 
{ "@attributes": { "name": "weight" }, "value": "0.5" }, 
{ "@attributes": { "name": "stock" }, "value": "true" }, 
{ "@attributes": { "name": "EAN" }, "value": "1234" } ] }, 
"variations": {} },

How can I get brandName?

Upvotes: 1

Views: 71

Answers (3)

Andreas Jägle
Andreas Jägle

Reputation: 12270

This is a problem with some special characters in properties. The same happens if you have a json key like e.g. my-key which cannot be accessed in a property-way. Therefore you can use the fallback array access to get the value:

var x = { "product": [ { "@attributes": { "ID": "123456789" }, "name": "Name of the product"}]}

// [0] not required when looping through the list...
var id = x.product[0]["@attributes"].ID

console.log(id); // 123456789

EDIT: to read it dynamically, you could use some helper function like so (can be extended, if the path is more dynamic)

var key = "@attributes.ID";

function getData(object, key) {
  var keys = key.split(".");
  return object[keys[0]][keys[1]];
}

// sample call for demo purpose
var res = getData(x.product[0], key);
console.log(res);

And call the getData() method from your expression like this:

{{ getData(product, value) }} 

EDIT2: for a fully dynamic structure:

function getDataDyn(object, keystr) {
  var keys = keystr.split(".");
  return digg(object, keys);
}

function digg(obj, keys) {
  if(keys.length === 1) {
    return obj[keys[0]]
  } else {
    return digg(obj[keys[0]], keys.splice(1));    
  }
}

// sample call for demo purpose
var result = getDataDyn(x.product[0], key);
console.log(result);

Upvotes: 1

dfsq
dfsq

Reputation: 193301

There are no very elegant solution for this problem. However, you can simplify things significantly if you don't parse key manually and just delegate it to existent Angular services. In your case $parse can already do it.

I would wrap this functionality into custom filter so it could be something like this:

.filter('key', function($parse) {
    return function(context, name) {
        return $parse('this' + name)(context);
    };
});

And them in HTML:

{{ product | key:name }} // name is "['@attributes']['ID']"

Demo: http://plnkr.co/edit/jIIhXDW6S62IYrBXIB94?p=preview

Upvotes: 0

iamalismith
iamalismith

Reputation: 1571

You could use {{product['@attributes'].ID}}

Or if the first object key is dynamically named you could do: {{product[Object.keys(product)[0]].ID}}

Object.keys(obj) returns an array of keys for a given object https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

Upvotes: 1

Related Questions