keke
keke

Reputation: 105

Complex JSON structure + Dojo Selects

I have a data structure and i don't know how to manage it properly. I must use Dojo, so i chose JSON to solve this problem. The structure i'm talking about is on the bottom of this post. Go check it before you read the following text.

The problem: i must have 3 Selects. The first select will contain the "first level" (a, b, c). The second one will contain the "second level" (aa, ab, ...) and so on.

The data in each Select (except the first one) should vary depending on what was chosen in the previous Select.

For example, if i choose "a" in the first Select, i should only see the "aa, ab, ac" in the second Select. Then if i choose "ac" in the second one, i should only see "aca, acb, acc".

Note that there are cases when there is no "third level". In this case, the third select should be hidden (OR if it's too hard to manage, just be empty).

Now for the references. If i choose "d" in the first Select, i should only see "aa, bc, ca" as options of the second Select. Then, if i choose "cc" in the second Select, i should see "cca, ccb, ccc" in the third Select. This should not be static of course. In my example, if the "c -> cc" subtree will change, the contents of "d -> cc" should change too.

Now for the questions:

1) How do i make something like that work using Dojo? If it was Vanilla JS it would be obvious for me, but i can't figure how to make it work with all these object stores and such things.

2) How do i make References work with that kind of structure? I could make it work on a simple JSON, but when it gets so complex i'm completely lost.

3) How do i present the structure? As a single JSON? Or should i split it into several parts?

Thanks in advance!

a
    aa
        aaa
        aab
    ab
        aba
    ac
        aca
        acb
        acc
b
    ba
    bb
    bc
        bca
c
    ca
        caa
        cab
    cb
        cba
        cbb
    cc
        cca
        ccb
        ccc
d
    <ref to aa subtree>
    <ref to bc subtree>
    <ref to ca subtree>

Upvotes: 0

Views: 58

Answers (1)

Dimitri Mestdagh
Dimitri Mestdagh

Reputation: 44685

Well, you can represent it as an object, for example:

var myData = {
    a: {
        aa: ['aaa', 'aab'],
        ab: ['aba'],
        ac: ['aca', 'acb', 'acc']
    },
    b: {
        ba: null,
        bb: null,
        bc: ['bca']
    },
    c: {
        ca: ['caa', 'cab'],
        cb: ['cba', 'cbb'],
        cc: ['cca', 'ccb', 'ccc']
    },
    d: {}
};
myData.d.aa = myData.a.aa;
myData.d.bc = myData.b.bc;
myData.d.ca = myData.c.ca;

But anyways, the implementation will be quite complex as well. First of all I would suggest writing a function that gets the labels of each level, depending on the parameter. For example:

var getObjectData = function(object) {
    var data = [];
    for (var key in object) {
        if (object.hasOwnProperty(key)) {
            data.push({
                name: key,
                value: object[key]
            });
        }
    }
    return data;
};
var getData = function(obj) {
    var data = [];
    if (obj === undefined) {
        return getObjectData(myData);
    } else if (obj instanceof Array) {
        return obj.map(function(value) {
            return {
                name: value,
                value: null
            };
        });
    } else {
        return getObjectData(obj);
    }
    return data;
};

This will return the proper data that should be available inside the store, containing the label ("a", "b", "c", ...) and the object structure of the next level.

Then you can write something like this:

registry.byId("level1").setStore(new ObjectStore({
     objectStore: new Memory({
        data: getData(),
        idProperty: 'name'
    })
}));
var getNextLevel = function(value) {
    var data = getData(this.store.objectStore.get(value).value);
    if (this.nextLevel) {
        if (data.length > 0) {
            domStyle.set(registry.byId(this.nextLevel).domNode, "display", "inline-table");
            registry.byId(this.nextLevel).setStore(new ObjectStore({
                objectStore: new Memory({
                    data: data,
                    idProperty: 'name'
                })
            }));
        } else {
            domStyle.set(registry.byId(this.nextLevel).domNode, "display", "none");   
        }
    }
};
registry.byId("level1").on("change", getNextLevel);
registry.byId("level2").on("change", getNextLevel);

This will, retrieve the data (using the functions earlier) when the value changes and it will then populate the store of the next level with that data.

This is not a complete solution yet though. Because you still need to do some intialization, but it gives you an idea of how you could approach this situation.

An example: http://jsfiddle.net/ekoronra/

Upvotes: 1

Related Questions