2017-02-07 54 views
2

我是Knockout新手,在使用Knockout貼圖插件時,無法理解如何「編輯」視圖模型。希望有人能幫助我。我有一份清單。以下是一個類似的例子。基本上多個組有多個文件。如何添加東西到Knockout映射視圖模型?

[ 
    { 
     "group": "Alice", 
     "files": [ 
      {"filename": "red.mp3", "length": 5}, 
      {"filename": "blue.mp3","length": 6}, 
      {"filename": "yellow.mp3","length": 5} 
     ] 
    }, 
    { 
     "group": "Bob", 
     "files": [ 
      {"filename": "green.mp3","length": 2}, 
      {"filename": "purple.mp3","length": 10} 
     ] 
    } 
] 

而且我可以從這個基本模型:

$.getJSON('api/get-list', function(data) 
    { 
     view = ko.mapping.fromJS(data); 
     ko.applyBindings(view); 
    }); 

它的工作原理,我已經成功地結合起來在HTML所以它的可見光和所有在這一領域是好的。但是,我需要添加幾件事情,而且我不確定如何執行此操作。更重要的是,如何幹淨利落地做到這一點。

我用複選框輸出文件,並且我想綁定一個'select'屬性。我已經能夠通過在後端添加字段來做到這一點,但不希望這樣做,因爲它真的不應該在那裏。還需要顯示當前選擇的人數,出於多少,每個組和總數。

所以,基本上我想是這樣的:

{ 
    "formSubmit": ?, 
    "totalNumberOfFiles": ?, 
    "totalNumberOfSelectedFiles": ?, 
    "groups": 
    [ 
     { 
      "group": "Alice", 
      "numberOfFiles": ?, 
      "selectedFiles": ?, 
      "files": [ 
       { 
        "filename": "red.mp3", 
        "length": 5, 
        "selected": boolean 
       }, 
       ... 
      ] 
     }, 
     ... 
    ] 
} 
  • 雖然,例如,numberOfFiles甚至可能是沒有必要?可以從files.length得到嗎?
  • 而且selectedFiles應該是一個函數/觀測值,用於計算選定文件的數量(看起來如何?)或者它應該是一個以某種方式添加/刪除的列表(以及如何做到這一點?)
  • 我怎麼能在submit函數中獲得當前選中文件的列表,以便我可以將它們發回服務器?
  • 無論哪種方式,我如何用這些東西來「增強/充實/包裝」從服務器獲得的基本數組,而不是太雜亂?

基本上,我知道(能弄清楚)如何做綁定時只是模型工作,但不知道如何建造起來的好方法使用映射插件的時候(我真的不想手動)。

希望有人能幫助我,因爲我只是當您使用ko.mapping.fromJS每個屬性轉換爲可觀察到的和每個數組轉換爲observableArray不能算出這個

回答

3

主視圖模型MyViewModel有一個FileGroups列表,它使用一個使用自定義映射對象的映射進行初始化。該對象有一個「創建」回調(如http://knockoutjs.com/documentation/plugins-mapping.html中所述),用於實例化新的文件組。

文件組構造,只是創造新的子視圖模型「選擇」屬性中加入是它的默認值之前。

此外,主視圖模型具有兩個計算觀測:

  1. NUMBEROFFILES:返回文件的每一個文件組
  2. selectedFiles總數:返回包含在每一個文件組
  3. 全部所選文件的數組

提交方法有一個簡單的警報來演示如何訪問所選文件的數組。

// data obtained from the server 
 
var data = [ 
 
    { 
 
    "group": "Alice", 
 
    "files": [ 
 
     { "filename": "red.mp3", "length": 5 }, 
 
     { "filename": "blue.mp3", "length": 6 }, 
 
     { "filename": "yellow.mp3", "length": 5 } 
 
    ] 
 
    }, 
 
    { 
 
    "group": "Bob", 
 
    "files": [ 
 
     { "filename": "green.mp3", "length": 2 }, 
 
     { "filename": "purple.mp3", "length": 10 } 
 
    ] 
 
    } 
 
]; 
 

 
// sub view model representing a single file grouping 
 
var FileGroup = function (data) { 
 
    data.files.map(f => f.selected = false); 
 
    ko.mapping.fromJS(data, {}, this); 
 
} 
 

 
// main view model 
 
var MyViewModel = function (data) { 
 
    this.fileGroups = ko.mapping.fromJS(data, { create: options => new FileGroup(options.data) }); 
 

 
    this.numberOfFiles = ko.computed(() => { 
 
    return this.fileGroups().reduce((total, fg) => { 
 
     total += fg.files().length; 
 
     return total; 
 
    }, 0); 
 
    }, this); 
 

 
    this.selectedFiles = ko.computed(function() { 
 
    return this.fileGroups().reduce((selectedFiles, fg) => { 
 
     selectedFiles.push.apply(selectedFiles, fg.files().filter(f => f.selected())); 
 
     return selectedFiles; 
 
    }, []) 
 
    }, this); 
 

 
    this.submit = function() { 
 
    alert("FILES POSTED TO SERVER: " + this.selectedFiles().length); 
 
    } 
 
} 
 

 
var viewModel = new MyViewModel(data); 
 
ko.applyBindings(viewModel);
.fileGroup { 
 
    border: 1px solid lightgray; 
 
    margin-bottom: 15px; 
 
    padding: 10px; 
 
} 
 

 
.selected { 
 
    border: 1px solid lightgreen; 
 
    margin-bottom: 15px; 
 
    padding: 10px; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js" type="text/javascript"></script> 
 

 
<div data-bind="foreach: fileGroups"> 
 
    <h3 data-bind="text: group"></h3> 
 

 
    <div data-bind="foreach: files" class="fileGroup"> 
 
    <input type="checkbox" data-bind="checked: selected"> 
 
    <span data-bind="text: filename" /> 
 
    </div> 
 
</div> 
 

 
<h4>Number of Files: <span data-bind="text: numberOfFiles"></span></h4> 
 

 
<div data-bind="foreach: selectedFiles, visible: selectedFiles().length > 0" class=selected> 
 
    <span data-bind="text: filename" /> 
 
</div> 
 

 
<button data-bind="click: submit">Submit</button>

+0

這使得它* *得多想更清楚我居然能進一步得到這個淘汰賽道路上,現在我自己。非常感謝! – Svish

相關問題