2017-02-07 30 views
2

Я новичок в Knockout, и у меня возникли проблемы с пониманием того, как «редактировать» модель представления при использовании плагина Nockout mapping. Хотел, чтобы кто-то помог мне. У меня есть список со списками. Ниже приведен подобный пример. В основном несколько групп с несколькими файлами.Как добавить материал в модель отображения нокаута?

[ 
    { 
     "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 быть функцией/наблюдаемым, которая подсчитывает количество выбранных файлов (как это выглядела?), Или скорее это список, который каким-то образом был добавлен/удален (и как это сделать?)
  • И как я мог в функции отправки получить список выбранных файлов, чтобы я мог отправить их обратно на сервер?
  • И в любом случае, как мне «улучшить/обогатить/обернуть» базовый массив, который я получаю с сервера с этими вещами, не слишком грязным способом?

В принципе, я знаю (могу понять), как сделать привязку, когда только модель работает, но не понимаю, как построить его в хорошем смысле, используя отображение плагин (и я действительно не хотят делать это вручную).

Надежда кто-то может помочь мне, потому что я просто не могу понять это

ответ

3

При использовании ko.mapping.fromJS каждое свойство преобразуется в наблюдаемой и каждый массив преобразуется в observableArray.

Основная модель просмотра, MyViewModel, имеет список файловых групп, который инициализируется сопоставлением, которое использует настраиваемый объект сопоставления. Этот объект имеет обратный вызов «create» (как описано в http://knockoutjs.com/documentation/plugins-mapping.html), который создает новую файловую группу.

В FileGroup конструктор , перед созданием новой модели вид к югу, свойство «выбранный» добавляется с ложным является его значение по умолчанию.

Кроме того, основной вид модель имеет два вычисляемых наблюдаемые:

  1. numberOfFiles: возвращает общее количество файлов в каждом файловой группе
  2. selectedFiles: возвращает массив, содержащий все выбранные файлы в каждом FileGroup

В способе submit есть простое оповещение, чтобы продемонстрировать, как получить доступ к массиву выбранных файлов.

// 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

Это сделало * много * яснее думаю, что я на самом деле быть в состоянии получить дальше по этому пути Knockout теперь самостоятельно. Спасибо огромное! – Svish