[dojo-contributors] MVC support for dijit based on dojo.Stateful

Rahul Akolkar rahul.akolkar at gmail.com
Sun Mar 6 17:00:36 EST 2011


Hi Bill,

Inline.

On Sat, Mar 5, 2011 at 9:09 PM, Bill Keese <bill at dojotoolkit.org> wrote:
> OK, so part of what I was asking was whether parent.get("ref") just returned
> parent.ref, or if it computed the return value by tracing up the tree.
> From your response it's clear that it just returns parent.ref.  So in the
> worst case, every node with a "ref" setting will trace up to <body> looking
> for a parent ref.   That still sounds CPU intensive but maybe not the end of
> the world.
<snip/>

Correct, thats the worst case. Usually, portion of the bound dijits
will locate their parent data binding context much closer (than
<body>).


> Note: you probably should be calling dojo.getObject() rather than
> dojo.eval(), will you ever pass eval() more than a dot separated identifier?
<snap/>

Its a bit of a carte blanche, but the idea is to enable more involved
expressions if such make sense for the application (as a simple
example, the ? : ternary operator could be used here).


> --------
> I'm still confused by ref vs. binding.
<snip/>

There are two different things as follows:

1. ref:

 * When you think ref, think string. The ref is what enables the dijit
to locate its initial data binding node (in a StatefulModel).
 * There are currently two lexical spaces for ref: (a) legal
JavaScript expression for refs on outermost bound widget that resolves
to a StatefulModel node, and (b) legal relative model node property
names on nested bound widgets. These two needn't be the only ones.
 * The ref is doc'ed as "[const] String", i.e. it is provided once at
instantiation (either via markup i.e. ref="foo" or
data-dojo-props="{ref:'foo'}" or programmatically once we have that
working).

2. binding:

 * When you think binding, think actual node in StatefulModel. When
the widget startup is complete, this is what the ref resolves to once
the relevant ref semantics are applied.
 * The value space for binding is all StatefulModel nodes.
 * The widget binding can be updated programmatically per application
needs. Sidebar: The utility of describing bindings via relative refs
for nested widgets is that they will automatically resolve themselves
to new StatefulModel nodes if the parent context (or any ancestor) is
changed programmatically.

The purpose of this separation is to differentiate the lexical space
for binding specification from its value space, so more intelligent
things can be done while transforming between the two spaces during
page load.


>    In one of your test files you
> have:
>
> dijit.byId("view").set("binding", binding);
>
> Yet, there's no "binding" attribute declared in _DataBindingMixin.js.
>
<snap/>

Right, thats an example of updating the data binding by pointing to a
different StatefulModel node programmatically. This is how one would
update bindings beyond page load. A better example is in the "bill
to/ship to" or order form demo (check out the two buttons).


> In one of your test files you have:
>
> <input id="taxes" dojoType="dijit.form.NumberTextBox"
> ref="loanModel.Taxes"/>
>
> In that example ref is both the StatefulModel object and the attribute
> inside of it.   (loanModel.Taxes is a number, right?)
>
<snip/>

In above, the ref is the string "loanModel.Taxes" which resolves at
startup to said node in the application StatefulModel (this node
reference becomes the "binding"). The node at loanModel.Taxes is not a
number (its a StatefulModel node). The actual numeric value is here:
loanModel.Taxes.value but its uncommon to reference it using that
expression (the bind takes care of all the value and meta-data
synchronization).


> ------
>
> Have you thought that users might try to specify ref (or is it binding?) as
> an object rather than as a string?   Something like:
>       new dijit.form.TextBox({ref: myStatefulModel.employeeName})
<snap/>

Yes, this will be possible as follows (note the quotes as its a string):

  new dijit.form.TextBox({ref: 'myStatefulModel.employeeName'})


> That's not quite right because it will end up as though I had done this:
>       new dijit.form.TextBox({ref: "John Smith"})
<snip/>

Its not right for a different reason: myStatefulModel.employeeName
would evaluate to the model node i.e. its binding, whereas ref is a
string (please see above).


> but anyway it seems like the app should be able to specify the Stateful
> object being bound as an object rather than as a string name of a global
> variable.
>
<snap/>

Yes, this will be possible as follows (when I'm done, if its not already):

  new dijit.form.TextBox({binding: myStatefulModel.employeeName})


> Note that we have this pattern in other widget parameters, for example
> DateTextBox.value is a Date object, but when you construct a DateTextBox or
> call set("value", ...) you can pass in a string for the value and it gets
> converted.   In your case it seems like ref (or is it binding?) should be an
> Object, but you allow a string as a parameter to the constructor or argument
> to set("ref", ...) .
<snip/>

Right, there are similarities.


> ----------
> Here's a test case for you to add, it seems like this should work, but it
> won't work w/your current code:
>     myWidget = new myWidget({ref: "foo.bar"})    <--- can't eval ref yet
> since no parent
>     myWidget.placeAt(dojo.body());
>     myWidget.startup()  <--- should set widget's value according to model
>     myWiget.set("ref", "baz.bam") <-- should reset widget's value according
> to new model
>
<snap/>

+1 to adding the above test case with the following change to last line:

+   myWiget.set("ref", "baz.bam")
-   myWidget.set("binding", baz.bam);

BTW, I'll be looking at programmatic instantiation next (i.e. moving
data binding mixin function from postCreate() to startup() etc.).

-Rahul


More information about the dojo-contributors mailing list