FarCreek
FarCreek

Reputation: 47

Vue.js: v-for loop reverses order in safari

I have the following Vue template:

<div id="app">
[[gameList | json]]
<br><br>
<table>
    <tr v-for="gameSet in gameList">
        <td>[[gameSet.season    | json]]</td>
        <td>[[gameSet.offSeason | json]]</td>
    </tr>
</table>



Accompanied by the following Vue code:

Vue.config.delimiters = ["[[", "]]"];
var app = new Vue({

el: "#app",

data: {
    gameListJSON: '[{"id":"9","season":{"season0":{"type":"player","value":"23"},"season1":{"type":"staff","value":"64"},"season2":{"type":"visitor","value":"5"}},"offSeason":{"offSeason0":{"type":"player","value":"54"},"offSeason1":{"type":"staff","value":"43"},"offSeason2":{"type":"visitor","value":"45"}}}]'
},
computed: {
    gameList: function () {
        var list;

        list = $.parseJSON(this.gameListJSON);

        $("#output").html(JSON.stringify(list));
        return list;
    }
}
});

It renders properly in all the browsers I've tested so far, except for Safari. For some reason it shows all the objects that get parsed from JSON in reverse order. This only happens during rendering, as soon as I add the v-for loop to the code. Without it, gameList renders as expected. Within the computing function, the order is still intact, as can be seen when it gets printed in the #output div.

What I've gathered from the Vue docs, the following warning might be what I'm running into.

When iterating over an Object, the order is based on the key enumeration order of Object.keys(), which is not guaranteed to be consistent in all JavaScript engine implementations.

Can anyone confirm this is why the rendering is reversed?

And what would be the best way to preserve the order in which the objects get rendered?

You can find a working example in this JSFiddle: http://jsfiddle.net/d9u6fump/

Thank you all in advance.

EDIT:

I couldn't get it to order on the property name with the orderBy function so I ended up creating a custom filter:

Vue.filter('orderedJSON', function(gameSet){
    var json, counter;

    json = {};

    counter = 0;
    for( var gameElement in gameSet){
        gameElement = gameElement.replace(/[0-9]/g, '');
        gameElement += counter;

        json[gameElement] = gameSet[gameElement];
        counter++;
    }

    return JSON.stringify(json);
});

While this works, it still feels very hacky to have to force the order this way. So I'm still open for a more elegant solution.

Upvotes: 1

Views: 1414

Answers (1)

pespantelis
pespantelis

Reputation: 15372

As creator said:

This is expected. v-for on object does not guarantee enumeration order, it's determined by the JS engine. Use orderBy for explicit ordering.

Upvotes: 1

Related Questions