2014-11-24 108 views
0

我有一個綁定到記錄數組的dojox/mvc/Repeat區域。Dojo MVC的條件顯示

在Repeat的行內有一個字段(記錄的id),它應該是一個簡單的顯示輸出,如果記錄已經保存到數據庫中,但是如果記錄是新的,它應該是一個TextBox (用戶必須輸入值)。

如何優雅地解決這個問題?我對Dojo相當陌生,而且其MVC部分的記錄很少。

+0

您可以使用變換將disabled變量設置爲true或false。如果你使用解析變換,這是在出路上調用,格式化,在途中將嘗試把小提琴放在一起。 – tik27 2014-11-25 23:16:51

+0

謝謝,但我想爲記錄的兩種狀態顯示不同的項目,所以僅僅使用變換器綁定TextBox的禁用屬性並不是一個真正的選擇。我正在製作一個小提琴,它可以用不同的變形金剛綁定2個項目的顯示屬性。 – sola 2014-11-26 09:35:30

回答

0

一種二次,較不復雜的解決方案:

綁定 「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 --> 
1

最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 --> 
1

密新/變壓器的做法是我腦子裏想的,太。我要添加的兩件事是開箱即用的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

+0

非常有見地的答案。我想我會保存CssToggleMixin以備後用,它看起來像是一種使用屬性進行類切換的強大方式。聽起來像是應該成爲Dijit核心部分的東西。 – sola 2014-11-29 14:57:24