0

I'm encountering annoying issues. I'm struggling on it for many hours.

I need to render my data (fetched by an ajax call) ordered by the value date

So the JSON looks like

user_a: 
   { message: 
      { text: 'Hello',
        date: 1547093749649,
       },
  user_b: 
   { message: 
      { text: 'Hi',
        date: 1547093749639,
        }
   }

When my JSON come from the database, the object with text: Hello is always at the top. But surprisingly when I want to display the data with some HTML, the render is displayed randomly. sometimes user_b come first, other time this is user_a.

I've also tried to rebuild the object by generating a new one based on js sorting method

sortable.sort(function(a,b){
          return b - a
        })

but no effect.

Maybe it's related to my iteration method

var html = '<div>'

Object.keys(object).map((node,i) => {

html =+ '<p>'+object[node]['message']['text']+'</p>'

})

html =+ </div>

I'm confused and I don't know how to force HTML to render my object keys/value in the same order than the JSON obj.

bugfreerammohan
  • 1,443
  • 1
  • 5
  • 18
John doe
  • 3,025
  • 4
  • 20
  • 44
  • 1
    properties order in objects is not guaranteed in JavaScript; you need to use an Array. please read this for more info https://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order – Jayakrishnan Jan 10 '19 at 12:51
  • @Jayakrishnan [It is guaranteed now](https://www.stefanjudis.com/today-i-learned/property-order-is-predictable-in-javascript-objects-since-es2015/), but yeah, if you need sorting you should have an array instead of relying of property order. @JohnDoe You should show what your `sortable` variable looks like. You cannot sort the properties of an object, only the keys of an array – Juan Mendes Jan 10 '19 at 12:58

6 Answers6

1

Using Object.entries, Array#map, Array#sort, Template literals and destructuring.

First sort them by descending according to their date to preserve the order.

const data={user_a:{message:{text:"Hello",date:1547093749649}},user_b:{message:{text:"Hi",date:1547093749639}}};

const res = Object
.entries(data)
.sort(([,a], [,b])=>b.message.date - a.message.date)
.map(([user,{message}])=>{
  return `
    <div>
      <p>${user}; ${message.text}; ${message.date}</p>
    </div>
  `
}).join("");

document.body.innerHTML = res;
kemicofa ghost
  • 14,587
  • 5
  • 63
  • 112
0

sort the properties into an array, then loop over them:

var obj = {
  user_a: {
    message: {
      text: 'Hello',
      date: 1547093749649,
    }
  },
  user_b: {
    message: {
      text: 'Hi',
      date: 1547093749639,
    }
  }
};

var html = '<div>';
var props = Object.keys(obj).sort((a, b) => obj[a].message.date - obj[b].message.date);
props.forEach(x => html += '<p>'+obj[x].message.text+'</p>')
html += '</div>';

console.log(html);
BenG
  • 13,680
  • 4
  • 41
  • 57
0

You can extract the values of users object to an array and sort it by the date property:

const users = { 
    user_a: {
        message: {
           text: 'Hello',
           date: 1547093749649,
        } 
    },
    user_b: {
        message: { 
           text: 'Hi',
           date: 1547093749639,
        }
    }
};

const sortedUsers = Object.values(users).sort((userA, userB) => userA.message.date - userB.message.date);

console.log(sortedUsers)
antonku
  • 5,707
  • 2
  • 11
  • 17
0

You should convert your object into an array and then sort

const obj = {
  user_a: {
    message: {
      text: 'Hello',
      date: 1547093749649,
    },
  },
  user_b: {
    message: {
      text: 'Hi',
      date: 1547093749639,
    }
  }
};

const objArray = Object.keys(obj).map((key) => {
  // Merge the key (user_a) into the inner object as a name property
  return {...obj[key], name: key};
});

// Now sort the array by date or whatever else you need
console.log(objArray.sort((a,b) => a.message.date - b.message.date));
Juan Mendes
  • 80,964
  • 26
  • 138
  • 189
0

Try this:

var html = '<div>';
 Object.keys(obj).sort((node1, node2) => {
        return obj[node1]['message']['date'] - obj[node2]['message'];['date']
    })
    .map((node,i) => {
        html =+ '<p>'+object[node]['message']['text']+'</p>'
    });
    html =+ </div>;
Rahul Kant
  • 33
  • 8
0

I finally found a workaround.

i converted the object into an array

[
   { text: 'Hello',
     date: 1547093749619,
     user:b
   },
   { text: 'Hi',
     date: 1547093749639,
     user:a
   },
]

then i rebuilt the array by using sort

                   var sortable = []


                    for(var i = 0; i < array.length; i++){
                      sortable.push(array[i]['date'])
                    }



                    sortable.sort(function(a,b){
                     return b - a
                    })

                   var new_array = []

                   for(var i = 0; i < sortable.length; i++){
                    for(var j = 0; j < array[i].length; j++){
                     if(sortable[i] === array[j]['date']){
                       new_array.push(array[j])
                     }
                    }
                  }

That solution fixed my problem. I figured out that javascript Object are randomly sorted and there is nothing i can do to force a sorting. However it's different for Array that are always displayed in the right order.

John doe
  • 3,025
  • 4
  • 20
  • 44