0

I have data from backend in my js like this:

var list = {
    "6": {
        "id": 6,
        "name": "John",
        "age": 31
    },
    "42": {
        "id": 42,
        "name": "Alex",
        "age": 25
    },
    "3": {
        "id": 3,
        "name": "Tim",
        "age": 58
    },
};

Then I need to display this data in my angular html template through ngFor directive. But first I have to get an array of object keys:

var listKeys= Object.keys(list);

Next I can output data in template:

<div *ngFor="let item of listKeys">
    <p>{{list[item].id}}</p>
    <p>{{list[item].name}}</p>
    <p>{{list[item].age}}</p>
    <hr>
</div>

But the problem is that order of my data changed. I have in listKeys next array ["3", "6", "42"]. But I want to have original order in that one ["6", "42", "3"]. One of solutions that I have found is make keys as not numeric string. For example:

var list = {
    "+6": {...},
    "+42": {...},
    "+3": {...},
};

But I don't have access to backend. I need another solution.


P.S. The way in which I get data from the backend

  getData() {
    this._dataService.getList(this.name, this.age).subscribe(res => {
      this.list = JSON.parse(JSON.stringify(res));
      this.listKeys = Object.keys(this.list);
    });   
  }
11
  • 2
    Use an array instead of an object? what does Object.keys(list) output ? Commented Mar 28, 2018 at 10:49
  • The order of the properties in an object is not guaranteed in JS. Commented Mar 28, 2018 at 10:50
  • Object.keys(list) output ["3", "6", "42"] --- plnkr.co/edit/JEe5bMbdPaTqVgY3IuOs?p=info Commented Mar 28, 2018 at 10:53
  • You don't need access to the backend, data should always be ordered by the consumer unless it is a subset of bigger data such as paged data etc... Anyway your original list object actually is not iterated over in the order you think. See Property Traversal Order - As mentioned above, to guarantee the order add the items to an array in the order you prefer. Using an object in this case is not correct. Commented Mar 28, 2018 at 10:58
  • @Nope ... I assumed the object in list was the result of a JSON.parse ... @ironfist, exactly how is the data coming from the backend, and how does the var list get defined? Commented Mar 28, 2018 at 11:21

2 Answers 2

1

By definition, an object is an unordered collection of properties. As a solution, you could use an array instead of an object:

The first step would be to convert the response from the server to an array in the same order.

// Original JSON string received from API
var jsonString = `{
    "6": {
        "id": 6,
        "name": "John",
        "age": 31
    },
    "42": {
        "id": 42,
        "name": "Alex",
        "age": 25
    },
    "3": {
        "id": 3,
        "name": "Tim",
        "age": 58
    }
}`;

// Array of ordered id's
const orderedIds = [];

// Find all id's in the JSON string and push them to the array
const pattern = /"?id"?\: (\d*)/g;
let match;
while (match = pattern.exec(jsonString)) {
	orderedIds.push(parseInt(match[1]));        
}
 
 
// parse the original JSON object
const originalList = JSON.parse(jsonString);


// resulting ordered Array
const result = [];

// Push the object in the array by order
for(x of orderedIds) {
	result.push(originalList[x]);
}

// Log the resulting array
document.getElementById("result").innerText = JSON.stringify(result);
<pre id="result"></pre>
The result will be an array of the objects in the same order as they appeared in the JSON string:

result = [
    {
        "id": 6,
        "name": "John",
        "age": 31
    },
    {
        "id": 42,
        "name": "Alex",
        "age": 25
    },
    {
        "id": 3,
        "name": "Tim",
        "age": 58
    },
];

After this you can use it in your template:

<div *ngFor="let item of result">
    <p>{{item.id}}</p>
    <p>{{item.name}}</p>
    <p>{{item.age}}</p>
    <hr>
</div>

this array does garantee the order of its values.

Sign up to request clarification or add additional context in comments.

6 Comments

But I get the data as an object from the server. Or should I transform an object into an array?
problem with transforming into an array - if done on the client, then you'll get the same 3, 6, 42 order
@ironfist you need to create an array of objects instead of the object in backend to have them in the same order, otherwise in client side you will get the object keys numerically sorted when iterating them.
I don't have access to backend - so while this is a good answer, it can't possibly be implemented
You could take the original JSON string, search through it to find all id's in order, and then take the object and create a new array out of it, ordered by the id's you took earlier.
|
0

This is bound to have edge cases, but adding it because it works

If you are getting the data from the backend in the form of JSON then you can do the following

note: var json is a placeholder, as you haven't shown HOW you get your data

var json = `{
    "6": {
        "id": 6,
        "name": "John",
        "age": 31
    },
    "42": {
        "id": 42,
        "name": "Alex",
        "age": 25
    },
    "3": {
        "id": 3,
        "name": "Tim",
        "age": 58
    }
}`;

var result = JSON.parse(json.replace(/\s?"(\d+)":/g, '"$1 ":'));
console.log(Object.keys(result));

Again, this is bound to fail, but I can't see any other way you can "fix" this on the client side - I thought JSON.parse "reviver" function would help, but it gets the properties in 3, 6, 42 order as well - so, no use at all

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.