Question

I'm trying to hook up a Select element with a Dojo store. The Select element is declared in HTML and I'm trying to give it a store in some JavaScript code.

It seems the Dojo documentation recommends against this and is in favor of programatically creating the Select element when using a store. However this is a yellow flag to me because I like to keep creation of HTML elements separate from their behavior. In this case, it would be ideal if I could keep the Select element in HTML and hook up the store in JavaScript.

Is the statement in the Dojo docs really the 'best practice' for this? I'm looking for opinions from experienced Dojo developers as I'm still getting my feet wet with Dojo.

Was it helpful?

Solution

Intuitively one would use select.set("store", store) to assign/change store to a dijit as all widgets are dojo/Stateful, but surprisingly it does not work.

Anyway there is a method select.setStore(store, selectedValue, fetchArgs) which (also surprisingly) is not deprecated and works.

Define dijit/form/Select without a store:

<select id="select1" data-dojo-type="dijit/form/Select"></select>​

Assign a store to it:

require([
    "dojo/ready",
    "dijit/registry",
    "dojo/store/Memory",
], function(
    ready, registry, Memory
) {

    ready(function() {

        var store1 = new Memory({
            idProperty: "value",
            data: [
                { value: "AL", label: "Alabama" },
                { value: "AK", label: "Alaska" },
                { value: "AZ", label: "Arizona" }
            ]           
        });

        var select1 = registry.byId("select1");
        select1.set("labelAttr", "label");
        select1.setStore(store1, "AZ");       
    });
});

See it in action at jsFiddle: http://jsfiddle.net/phusick/ZmsYV/

Adding some UX sugar to the aforementioned I would create dijit/form/Select disabled with single option e.g. Loading... and its final desired width:

<select
    id="select1"
    data-dojo-type="dijit/form/Select"
    data-dojo-props="disabled:true"
    style="width:150px;"
>
    <option>Loading...</option>
</select>​

Then I would enable it after calling setStore():

var select1 = registry.byId("select1");
select1.set("labelAttr", "label");
select1.setStore(store1);
select1.set("disabled", false);

See this enhanced version at work: http://jsfiddle.net/phusick/xdDEm/

OTHER TIPS

Debugging bad store data/definitions can get pretty nasty when doing so declaratively. Additionally, you may run into strange annoyance when trying to create multiple of the same widget following a declaratively built select/store combination. For example (pseudocode):

<div dojotype="dojox.data.QueryReadStore" url="someurl/blah.do" jsId="mystore"/>
<select dojotype="dijit.form.FilteringSelect" store="mystore">
</select>

The would in theory do what you want by binding mystore to the select, however if you were to create multiple of this widget, you'd have an id conflict with "mystore." As a workaround you'd have to do something like jsId="${id}_mystore" for both the jsId and the store's id.

One option if you would like to keep a declarative behavior is to have attachpoints for both your store and your select, then you can simply call selectwidget.set("store",mystore) after initialization.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top