Question

Ice cream! I want to make a list of all ice creams I have tried and keep the list ordered so my favourite ice creams are at the top and my least favourite are at the bottom. (The list should be ordered by how delicious the ice cream is.

If I model it in an array I can do something like this:

var iceCreamOrdredList = [
    {name: "Coconut"},
    {name: "Mint Chocolate Chip"},
    ...
    {name: "Banana"} /* Obviously noone really likes banana ice cream*/
}

The order of the array indicates that Coconut ice cream is preferred to Banana.

If I want to display my ice cream preferences in a dijit or dgrid, then I need to wrap the array in a store. A memory store is probably the most obvious choice. That means doing something like this:

var iceCreamStore = new Memory([data: iceCreamOrdredList]);

Whenever I try a new ice cream I want to add it to this data structure and allow all of my dijits/dgrids to update. This means that I should probably declare my store like this instead:

var iceCreamStore = new Observable(new Memory({data: iceCreamOrdredList}));

This for the most part works well.


One issue I haven't been able to resolve is if someone asks me something like this how to answer it:

'Root Beer' ice cream is my favourite. What is the position of 'Root Beer' in your priority list?

I can find 'Root Beer' in the store by doing this:

var someIceCream = iceCreamStore.query({name: "Root Beer"});

But this does not allow me to access the position of 'Root Beer' in the store.

I could also do something like this:

for(var i=0; i<iceCreamStore.data.length; i++){
    if(iceCreamStore.data[i].name == "Root Beer"){
        return i;
    }
}

But this seems 1) Heavy 2) Out of the spirit of the store API.


Doing the opposite is also tricky. Answering the question:

What is your nth favourite ice cream

Requires something along the lines of:

return iceCreamStore.data[n]

This seems very unstore like.


Reordering elements in the store is also challenging. Are there any good patterns for dealing with reordering? I could attach a priority field onto ice cream. Ie:

{name: "Cotton candy", order: 33}

But this means that when I insert or delete an ice cream I will need to update the order property on all ice creams. Yuck.

Was it helpful?

Solution 2

The best solution I found to this is to use an "OrderedStore". One implementation of this can be found in the DGrid test code. See here (see line 292):

https://github.com/SitePen/dgrid/blob/c8f08142b9ece66401dc3eef35371f4e98fa996e/test/data/base.js

To briefly summarize, an ordered store is a store which adds behaviour to the add, put and query methods of a store. On add and put the store must update the order property on it's children.

This an extract of the code:

return Observable(new Memory(lang.mixin({data: data,
    put: function(object, options){
        object.order = calculateOrder(this, object, options && options.before);

    return Memory.prototype.put.call(this, object, options);
    },
    // Memory's add does not need to be augmented since it calls put
    copy: function(object, options){
        /* Do this if you want copy functionality. */
    },
    query: function(query, options){
        options = options || {};
        options.sort = [{attribute:"order"}];
        return Memory.prototype.query.call(this, query, options);
    }
}, options)));

OTHER TIPS

If the ice cream names are unique, then I would set the Memory Stores idProperty field to "name". You can then do stuff like iceCreamStore.index["Root Beer"] because dojo stores keep an internal index on what position a certain id is at. Here is an example based on your code:

var iceCreamStore = new Observable(new Memory({data: iceCreamOrdredList, idProperty: "name"}));

And to get a particular index (which should be the same as your order), would be:

var priority = iceCreamStore.index["Root Beer"];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top