我有一個綁定到記錄數組的dojox/mvc/Repeat區域。Dojo MVC的條件顯示
在Repeat的行內有一個字段(記錄的id),它應該是一個簡單的顯示輸出,如果記錄已經保存到數據庫中,但是如果記錄是新的,它應該是一個TextBox (用戶必須輸入值)。
如何優雅地解決這個問題?我對Dojo相當陌生,而且其MVC部分的記錄很少。
我有一個綁定到記錄數組的dojox/mvc/Repeat區域。Dojo MVC的條件顯示
在Repeat的行內有一個字段(記錄的id),它應該是一個簡單的顯示輸出,如果記錄已經保存到數據庫中,但是如果記錄是新的,它應該是一個TextBox (用戶必須輸入值)。
如何優雅地解決這個問題?我對Dojo相當陌生,而且其MVC部分的記錄很少。
一種二次,較不復雜的解決方案:
綁定 「hasBeenSaved」屬性重複div中的隱藏文本。
將onChange事件放在隱藏字段上,該字段也會獲得重複的索引。
onChange事件僅根據記錄的hasBeenChanged屬性值隱藏不適合的字段。
的小提琴是在這裏:http://jsfiddle.net/asoltesz/8u9js6sz/5/
代碼:
hasBeenSavedChanged = function(field, index) {
var divToHide
if (field.value == true) {
divToHide = "idInputDiv"
}
else {
divToHide = "idOutputDiv"
}
var div = document.getElementById(divToHide + index);
div.style.display = "none";
}
require([
"dojo/_base/declare", "dojo/dom-style", "dojo/parser", "dojo/ready",
"dijit/_WidgetBase", "dijit/_TemplatedMixin",
'dojox/mvc/getStateful'
], function(
declare, domStyle, parser, ready,
_WidgetBase, _TemplatedMixin,
getStateful
){
// setting up the data model for MVC
model = {
items: [
{ id: 'id1',
hasBeenSaved: true
},
{ id: null,
hasBeenSaved: false
},
{ id: null,
hasBeenSaved: false
},
{ id: 'id3',
hasBeenSaved: true
}
]
};
model = getStateful(model);
ready(function(){
// Call the parser manually so it runs after our mixin is defined, and page has finished loading
parser.parse();
});
});
HTML:
<script type="dojo/require">at: "dojox/mvc/at"</script>
<div
data-dojo-type="dojox/mvc/Group"
data-dojo-props="target: model"
>
<span id="itemsCtl"
data-dojo-type="dojox/mvc/ListController"
data-dojo-props="model: model.items">
</span>
<div id="itemsRepeat"
data-dojo-type="dojox/mvc/Repeat"
data-dojo-props="children: at('rel:', 'items')"
>
<div
data-dojo-type="dojox/mvc/Group"
data-dojo-props="target: at('rel:', ${this.index})"
>
<span>Record: ${this.index}</span>
<input
id="hasBeenChanged${this.index}"
data-dojo-type="dijit/form/TextBox"
data-dojo-props="value: at('rel:', 'hasBeenSaved')"
onChange="hasBeenSavedChanged(this, '${this.index}');"
type="hidden"
></input>
<!-- This is displayed only when the record is new (not saved yet) -->
<div id="idInputDiv${this.index}"
>
<label for="idInput${this.index}">id:</label>
<input
data-dojo-type="dijit/form/TextBox"
id="idInput${this.index}"
data-dojo-props="value: at('rel:', 'id')"
></input>
</div> <!-- end conditionally hidden div -->
<!-- This is displayed only when the record has already been saved -->
<div id="idOutputDiv${this.index}" >
<label for="idInput${this.index}">id:</label>
<span
data-dojo-type="dojox/mvc/Output"
id="idOutput${this.index}"
data-dojo-props="value: at('rel:', 'id')"
></span>
</div> <!-- end conditionally hidden div -->
<hr/>
</div> <!-- end of row -->
</div> <!-- end of Repeat -->
</div> <!-- end of Group -->
最MVC上下的解決方案,我發現到目前爲止如下:
1) 我把「hasBeenSaved」物業成將迎來創紀錄的服務器端保存狀態的模型。由於DIV的「display」樣式屬性將綁定到hasBeenSaved模型屬性(一個是布爾型,另一個是字符串:「block」/「none」),因此該屬性將通過轉換綁定到視圖。
2) 在行內,我在id輸入字段周圍放置了一個有條件可見的div。這隻有在記錄是新的時纔可見,所以它的顯示樣式屬性綁定了一個與Dojo MVC綁定相關的適當轉換器。 對於id輸出字段也是這樣做的,但綁定上的轉換器不同,因爲只有當記錄已經保存時纔會顯示。
的的jsfiddle我已經使用原型此解決方案:http://jsfiddle.net/asoltesz/6t4dj1w7/15/
require([
"dojo/_base/declare", "dojo/dom-style", "dojo/parser", "dojo/ready",
"dijit/_WidgetBase", "dijit/_TemplatedMixin",
'dojox/mvc/getStateful'
], function(
declare, domStyle, parser, ready,
_WidgetBase, _TemplatedMixin,
getStateful
){
// setting up the data model for MVC
model = {
items: [
{ id: 'id1',
hasBeenSaved: true
},
{ id: null,
hasBeenSaved: false
},
{ id: null,
hasBeenSaved: false
},
{ id: 'id3',
hasBeenSaved: true
}
]
};
model = getStateful(model);
/**
* This mixin makes it possible to set the "display" style property of
* the DOM node (of any widget) as a Widget property and thus bind it to an MVC model
* when needed.
*/
declare("_DisplayAttributeMixin", [], {
// parameters
display: "block",
_setDisplayAttr: function(/*String*/ display){
this._set("display", display);
domStyle.set(this.domNode, "display", display);
}
});
/** Transformer methods for converting hasBeenSaved to visible/hidden values */
transfSavedToHidden = {format: function(hasBeenSaved){
console.log("transfSavedToHidden: " + (hasBeenSaved ? "none" : "block"));
return hasBeenSaved ? "none" : "block";
}};
transfSavedToVisible = {format: function(hasBeenSaved){
console.log("transfSavedToHidden: " + (hasBeenSaved ? "block" : "none"));
return hasBeenSaved ? "block" : "none";
}};
ready(function(){
// Call the parser manually so it runs after our mixin is defined, and page has finished loading
parser.parse();
});
});
的HTML標記:
<script type="dojo/require">at: "dojox/mvc/at"</script>
<div
data-dojo-type="dojox/mvc/Group"
data-dojo-props="target: model"
>
<div id="repeatId"
data-dojo-type="dojox/mvc/Repeat"
data-dojo-props="children: at('rel:', 'items')"
>
<div
data-dojo-type="dojox/mvc/Group"
data-dojo-props="target: at('rel:', ${this.index})"
>
<span>Record: ${this.index}</span>
<!-- This is displayed only when the record is new (not saved yet) -->
<div
data-dojo-type="dijit/_WidgetBase"
data-dojo-mixins="_DisplayAttributeMixin"
data-mvc-bindings="
display: at('rel:', 'hasBeenSaved')
.direction(at.from)
.transform(transfSavedToHidden)"
>
<label for="idInput${this.index}">id:</label>
<input
data-dojo-type="dijit/form/TextBox"
id="idInput${this.index}"
data-dojo-props="value: at('rel:', 'id')"
></input>
</div> <!-- end conditionally hidden div -->
<!-- This is displayed only when the record has already been saved -->
<div
data-dojo-type="dijit/_WidgetBase"
data-dojo-mixins="_DisplayAttributeMixin"
data-mvc-bindings="
display: at('rel:', 'hasBeenSaved')
.direction(at.from)
.transform(transfSavedToVisible)"
>
<label for="idInput${this.index}">id:</label>
<span
data-dojo-type="dojox/mvc/Output"
id="idOutput${this.index}"
data-dojo-props="value: at('rel:', 'id')"
></span>
</div> <!-- end conditionally hidden div -->
<hr/>
</div> <!-- end of row -->
</div> <!-- end of Repeat -->
</div> <!-- end of Group -->
密新/變壓器的做法是我腦子裏想的,太。我要添加的兩件事是開箱即用的Dijit功能,一個是dijitDisplayNone
類,另一個是attribute mapping功能。
雖然奇怪的是前者沒有文檔,但意圖可能是在Dijit代碼庫中私人使用。
儘管它有點駭人(並且可能會在將來的1.x Dijit版本中被破解),但覆蓋負責attribute mapping的Dijit代碼將允許您將widget屬性映射到切換的CSS類。
下面是一個使用上面的兩個代碼示例:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="//ajax.googleapis.com/ajax/libs/dojo/1.10.1/dojo/resources/dojo.css">
<link rel="stylesheet" type="text/css" href="//ajax.googleapis.com/ajax/libs/dojo/1.10.1/dijit/themes/dijit.css">
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/dojo/1.10.1/dojo/dojo.js" data-dojo-config="async: 1, parseOnLoad: 0"></script>
<script type="text/javascript">
require([
"dojo/_base/array",
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/dom-class",
"dojo/parser",
"dojox/mvc/getStateful",
"dijit/form/TextBox"
], function(array, declare, lang, domClass, parser, getStateful){
declare("CssToggleMixin", null, {
// summary:
// Mixin class to support widget attributes with toggleClass type.
// toggleClass type allows boolean value of an attribute to reflect existence of a CSS class in a DOM node in the widget.
_attrToDom: function(/*String*/ attr, /*String*/ value, /*Object?*/ commands){
// summary:
// Handle widget attribute with toggleClass type.
// See dijit/_WidgetBase._attrToDom() for more details.
var callee = arguments.callee;
array.forEach((function(){ return lang.isArray(commands) ? commands.slice(0) : [commands]; })(arguments.length >= 3 ? commands : this.attributeMap[attr]), function(command){
command.type != "toggleClass" ?
this.inherited("_attrToDom", lang.mixin([attr, value, command], {callee: callee})) :
domClass.toggle(this[command.node || "domNode"], command.className || attr, value);
}, this);
}
});
flipConverter = {
format: function (value) {
return !value;
},
parse: function (value) {
return !value;
}
};
model = getStateful({
items: [
{
value: "Foo",
hasBeenSaved: true
},
{
hasBeenSaved: false
},
{
hasBeenSaved: false
},
{
value: "Bar",
hasBeenSaved: true
}
]
});
parser.parse();
})
</script>
</head>
<body>
<script type="dojo/require">at: "dojox/mvc/at"</script>
<div data-dojo-type="dojox/mvc/WidgetList"
data-dojo-mixins="dojox/mvc/_InlineTemplateMixin"
data-dojo-props="children: at(model, 'items')">
<script type="dojox/mvc/InlineTemplate">
<div>
<span data-dojo-type="dijit/_WidgetBase"
data-dojo-mixins="CssToggleMixin"
data-dojo-props="value: at('rel:', 'value'),
noDisplay: at('rel:', 'hasBeenSaved').transform(flipConverter),
_setValueAttr: {node: 'domNode', type: 'innerText'},
_setNoDisplayAttr: {type: 'toggleClass', className: 'dijitDisplayNone'}"></span>
<span data-dojo-type="dijit/form/TextBox"
data-dojo-mixins="CssToggleMixin"
data-dojo-props="value: at('rel:', 'value'),
noDisplay: at('rel:', 'hasBeenSaved'),
_setNoDisplayAttr: {type: 'toggleClass', className: 'dijitDisplayNone'}"></span>
</div>
</script>
</div>
</body>
</html>
希望它會提供一些線索。
Best,Akira
非常有見地的答案。我想我會保存CssToggleMixin以備後用,它看起來像是一種使用屬性進行類切換的強大方式。聽起來像是應該成爲Dijit核心部分的東西。 – sola 2014-11-29 14:57:24
您可以使用變換將disabled變量設置爲true或false。如果你使用解析變換,這是在出路上調用,格式化,在途中將嘗試把小提琴放在一起。 – tik27 2014-11-25 23:16:51
謝謝,但我想爲記錄的兩種狀態顯示不同的項目,所以僅僅使用變換器綁定TextBox的禁用屬性並不是一個真正的選擇。我正在製作一個小提琴,它可以用不同的變形金剛綁定2個項目的顯示屬性。 – sola 2014-11-26 09:35:30