在http://dojo-sandbox.net/public/ef38d/1新例验证应用程序需要的“视图模式”,这是UI组件所关注的模型,包含两种模型以使其工作。
此外,原始问题中的更新意味着期望dojox/mvc/ModelRefController支持“递归路径监视”的概念,但它不支持。我也有一个印象,dojox/mvc/at支持递归路径监视将最有帮助http://dojo-sandbox.net/public/ef38d/1以及http://dojo-sandbox.net/public/e6946/0,虽然它不受支持。这种印象尤其来自http://dojo-sandbox.net/public/ef38d/1,它似乎想要观察dataModel.model.nextLevel.title
路径(尽管代码没有)。
虽然执行情况可能并不理想的东西,我能想到的,使样本工作的最佳方法是在这里:
<!DOCTYPE html>
<html>
<head>
<title>dojo/Stateful tree with dojox/mvc/getStateful</title>
<script type="text/javascript"
src="//ajax.googleapis.com/ajax/libs/dojo/1.10.0/dojo/dojo.js"
data-dojo-config="parseOnLoad: 0, async: 1, mvc: {debugBindings: 1}"></script>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/dojo/1.10.0/dojo/resources/dojo.css">
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/dojo/1.10.0/dijit/themes/claro/claro.css">
<script type="text/javascript">
require([
"dojo/_base/declare",
"dojo/Stateful",
"dojo/parser",
"dijit/Destroyable",
"dojox/mvc/getStateful",
"dojox/mvc/parserExtension",
"dojo/domReady!"
], function (declare, Stateful, parser, Destroyable, getStateful) {
var watchPath = (function() {
function getPathComps(path) {
return path === "" ? [] : typeof path.splice !== "function" ? path.split(".") : path;
}
function getObjectPath(o, path) {
for (var comps = getPathComps(path), i = 0, l = comps.length; i < l; ++i) {
var comp = comps[i];
o = o == null ? o : o[comp];
}
return o;
}
return function (model, path, callback) {
if (model && typeof model.watch === "function") {
var comps = getPathComps(path),
prop = comps.shift(),
remainder = comps,
observer = {
prop: prop,
remainder: remainder,
hProp: model.watch(prop, function (name, old, current) {
var hasRemainder = observer.remainder.length > 0;
if (old !== current) {
if (observer.hRemainder) {
observer.hRemainder.remove();
observer.hRemainder = null;
}
observer.hRemainder = watchPath(model[prop], remainder.slice(), callback);
}
callback(hasRemainder ? getObjectPath(old, observer.remainder) : old,
hasRemainder ? getObjectPath(current, observer.remainder) : current);
}),
hRemainder: watchPath(model[prop], remainder.slice(), callback),
remove: function() {
if (this.hRemainder) {
this.hRemainder.remove();
this.hRemainder = null;
}
if (this.hProp) {
this.hProp.remove();
this.hProp = null;
}
}
};
return observer;
}
};
})();
var States = declare([Stateful, Destroyable], {
constructor: function (model) {
var self = this;
}
}),
App = declare(Stateful, {
firstDisabled: false,
secondDisabled: false,
model: null,
constructor: function() {
this.switchModel();
},
createModel: function() {
var model = getStateful({
title: "Foo",
nextLevel: {
title: "Bar",
nextLevel: {
title: "Baz"
}
}
}),
states = new Stateful({
firstDisabled: model.nextLevel.title === "Foo",
secondDisabled: model.nextLevel.nextLevel.title === "Foo"
}),
h0 = watchPath(model, "nextLevel.title", function (old, current) {
states.set("firstDisabled", current === "Foo");
}),
h1 = watchPath(model, "nextLevel.nextLevel.title", function (old, current) {
states.set("secondDisabled", current === "Foo");
});
model.set("states", states);
model.nextLevel.set("states", states);
model.nextLevel.nextLevel.set("states", states);
model.destroy = function() {
if (h0) {
h0.remove();
h0 = null;
}
if (h1) {
h1.remove();
h1 = null;
}
}
return model;
},
switchModel: function() {
var oldModel = this.get("model"),
model = this.createModel();
if (oldModel) {
oldModel.destroy();
}
this.set("model", model);
}
});
window.app = new App();
parser.parse();
});
</script>
</head>
<body class="claro">
<script type="dojo/require">at: "dojox/mvc/at"</script>
<div data-dojo-type="dojox/mvc/Group" data-dojo-props="target: at(app, 'model')">
Selected:
<span data-mvc-bindings="innerText: at('rel:', 'title')"></span>
<select type="combo" data-dojo-type="dijit/form/Select"
data-dojo-props="value: at('rel:', 'title'), disabled: at('rel:states', 'firstDisabled')">
<option value="Foo">Foo</option>
<option value="Bar">Bar</option>
<option value="Baz">Baz</option>
</select>
<div data-dojo-type="dojox/mvc/Group" data-dojo-props="target: at('rel:', 'nextLevel')">
Selected:
<span data-mvc-bindings="innerText: at('rel:', 'title')"></span>
<select type="combo" data-dojo-type="dijit/form/Select"
data-dojo-props="value: at('rel:', 'title'), disabled: at('rel:states', 'secondDisabled')">
<option value="Foo">Foo</option>
<option value="Bar">Bar</option>
<option value="Baz">Baz</option>
</select>
<div data-dojo-type="dojox/mvc/Group" data-dojo-props="target: at('rel:', 'nextLevel')">
Selected:
<span data-mvc-bindings="innerText: at('rel:', 'title')"></span>
<select type="combo" data-dojo-type="dijit/form/Select"
data-dojo-props="value: at('rel:', 'title')">
<option value="Foo">Foo</option>
<option value="Bar">Bar</option>
<option value="Baz">Baz</option>
</select>
</div>
</div>
</div>
<div data-dojo-type="dijit/form/Button">Switch model
<script type="dojo/on" data-dojo-event="click" data-dojo-args="evt">
app.switchModel();
</script>
</div>
</body>
</html>
希望这有助于。
Best,-Akira
我希望mvc/at能够保留答案,并且我不需要用Stateful.Watch来获得这个密码。我需要花一些时间考虑如何将这个结合到我的解决方案中,因为它的一部分是生成的。再次感谢您对这个问题的及时和全面的回答。 – rmiles