2015-01-09 148 views
0

我有描述定義如下的自:嵌套可觀察到的在KnockoutJS

var my_data = { 
    types: { typeA: {fieldX: { type: "string"}}, 
      typeB: {fieldY: { type: "string"}} }, 
    entries: [{ type: "typeA", fieldX: "foo" }, 
      { type: "typeB", fieldY: "bar" }] 
    }; 

這個想法是,「類型」描述了呈現關於「條目」的每個索引的數據。此數據用於呈現通過RESTful接口(每個類型描述字段的輸入以及條目字段值的綁定)編輯JSON數據的表單。

我試圖設置一個表單在敲除允許'條目'被編輯。我首先創建一個HTML來創建一個確定類型的選擇框。爲此,我映射類型字典的數組:

function mapDictionaryToArray(dictionary) { 
    var result = []; 
    for (var key in dictionary) { 
     if (dictionary.hasOwnProperty(key)) { 
      result.push({ key: key, value: dictionary[key] }); 
     } 
    } 

    return result; 
} 

然後KnockoutJS代碼以顯示條目

<!-- ko foreach: entries --> 
      <select data-bind="options: editTestViewModel.types, 
           optionsText: 'key', 
           optionsValue: 'value', 
           value: type, 
           event: { change: editTestViewModel.drawType }"></select> 
      <div data-bind="attr: { id: $index() + 'typeFields' }" class="container"></div> 
<!-- /ko --> 

模型視圖:

function EditTestViewModel() { 
    var self = this; 

    self.entries = ko.observableArray(); 
    self.types = ko.observable(); 

    self.setTest = function(test) { 
     self.test = test; 
     self.types(mapDictionaryToArray(test.types())); 
     self.entries(ko.mapping.fromJS(test.entries(), self.stateMapping)()); 

    }; 

    self.editTest = function() { 
     $('#edit').modal('hide'); 
     testsViewModel.edit(self.test, { 
      entries: self.entries() , 
      types: self.types() 
     }); 
    }; 

    self.drawType = function(place) { 
     home = $('#typeFields'); 
     home.children().remove(); 
     for (var field in place.type) { 
      tag = $('<div class="input-group">').appendTo(home); 
      $('<span class="input-group-addon">' + field + '</span>').appendTo(tag); 
      $('<input type="text" class="form-control" data-bind="text: \'test\'">').appendTo(tag); 
     } 
    }; 

    self.stateMapping = { 
     'type': { 
      create: function(options) { 
       return options.data 
      } 
     } 
    } 
} 

var editTestViewModel = new EditTestViewModel(); 
ko.applyBindings(editTestViewModel, $('#edit')[0]); 

我遇到的問題是插入的數據看起來不是由KockoutJS處理的。類型選擇功能並填充相關字段,但字段值未填充(現在爲靜態「測試」)。 KnockoutJS是否支持動態插入的內容,如果是這樣,我試圖正確地綁定它?

+1

我要說的是,你正在試圖當然是可能的淘汰賽。我不確定試圖以這種方式動態插入html是正確的方式去做 - 雖然你有沒有考慮過使用[templates](http://knockoutjs.com/documentation/template-binding.html)? – 2015-01-09 20:51:23

+0

詹姆斯說了什麼,你認爲模板?如果你做得正確,你的Javascript中不應該有任何HTML。你可以很容易地在你的html模板中使用foreach和knockout!請檢查一下! – 2015-01-09 22:10:07

+1

OP:* KnockoutJS是否支持動態插入的內容,如果是這樣,我試圖正確地綁定它?* - > KnockoutJS是**意思是**,並且通過使用jQuery執行DOM操作,您正在更改視圖沒有Knockout知道你的模型。 – Tyblitz 2015-01-10 12:44:50

回答

1

感謝大家對OP的意見。

我重寫了使用模板。出於某種原因,我的印象是,觀察數據不能用於option.value存儲。這似乎並非如此(https://stackoverflow.com/a/27873057/1440598)。在構造函數中,我現在將類型設置爲每個條目的可觀察值。

改變選擇觸發模板字段更新: http://fiddle.jshell.net/jhwpn6dy/3/

HTML:

<div data-bind="text: data.test"></div> 

<div data-bind="template: { name: 'entry-template', foreach: entries, as: 'entry' }"></div> 

<script type="text/html" id="entry-template"> 
    <h3 data-bind = "text: entry.type">I'm an entry</h3> 
    <select data-bind="options: $root.type_keys, 
         optionsText: 'key', 
         optionsValue: 'key', 
         value: entry.type"></select> 
    <div data-bind="template: { name: 'field-template', foreach: $root.fieldList(entry), as: 'field' }"></div> 
</script> 

<script type="text/html" id="field-template"> 
    <div class="input-group"> 
     <span class="input-group-addon" data-bind="text: field"></span> 
     <input type="text" class="form-control" data-bind="attr: { 'aria-label': field }, value: entry[field]"/> 
    </div> 
</script> 

JS:

var data = { 
    types: { 
     typeA: { 
      fieldX: { 
       type: "string" 
      } 
     }, 
     typeB: { 
      fieldY: { 
       type: "string" 
      } 
     } 
    }, 
    entries: [{ 
     type: "typeA", 
     fieldX: "foo" 
    }, { 
     type: "typeB", 
     fieldY: "bar" 
    }], 
    test: "Hello" 
}; 

function MainViewModel(data_obj) { 
    var self = this; 

    self.data = data_obj; 
    self.type_keys = mapDictionaryToArray(data_obj.types);  

    for (var entry in data_obj.entries) { 
     data_obj.entries[entry].type = ko.observable(data_obj.entries[entry].type); 
    } 
    self.entries = ko.observableArray(data_obj.entries); 
    console.log(self.entries()); 
} 

MainViewModel.prototype.fieldList = function (entry) { 
    var self = this; 
    var keys = []; 

    for (var key in self.data.types[entry.type()]) { 
     if (entry.hasOwnProperty(key)) { 
      keys.push(key); 
     } 
    } 

    <!-- console.log(entry.type); --> 
    return keys; 
}; 

function mapDictionaryToArray(dictionary) { 
    var result = []; 
    for (var key in dictionary) { 
     if (dictionary.hasOwnProperty(key)) { 
      result.push({ key: key, value: dictionary[key] }); 
     } 
    } 

    return result; 
} 

var dataViewModel = new MainViewModel(data); 

ko.applyBindings(dataViewModel); 
+0

我很高興你想到:) – Tyblitz 2015-01-14 14:02:49