2012-05-26 1 views
9

Я пытаюсь решить небольшую проблему с отображением ko. Сценарий заключается в том, что моя ViewModel - это в основном коллекция объектов. Каждый из объектов создается из JSon вызова, таким образом:нокаут создать пустой объект из автоматически отображаемого наблюдаемого

var ViewModel = ko.observableArray(); 

$.getJSON(url, function(data) { 
    ViewModel.push(ko.mapping.fromJSON(data)); 
}); 

Это прекрасно работает, и я могу делать все вроде магии в моем HTML. Вопрос в том, что, например, я хочу добавить что-то в свою коллекцию, скажем, для поддержки сценария «Добавить и изменить» на стороне клиента. Я хотел бы сделать что-то вроде:

<input type="button" value="add new" data-bind="click: AddNew" /> 

И я хотел бы функцию AddNew в ViewModel быть что-то вроде:

function AddNew() { 
    this.push(// WHAT HERE?); 
} 

В основном нужно нажать объект, который идентичен другим уже существующий, но, конечно, со всеми скрытыми свойствами ...

Я думал о способе «клонирования» объекта из списка и установки всех наблюдаемых на пустой, но я не знаю, с чего начать. m испуган:/

ответ

6

Если вы собираетесь расширить свои функциональные возможности до редактирования/добавления на стороне клиента, я бы рекомендовал формализовать ваши объекты в js-классе, а затем отобразить эти объекты изнутри. Это позволит вам использовать ваши методы добавления на главной модели просмотра и легко создавать пустые экземпляры клиентской стороны.

Одно предостережение с плагиатом сопоставления заключается в том, что для обновления объектов он ожидает, что эти объекты были первоначально отображены плагином. Вот краткий пример того, как это можно сделать.

var YourObjectClass = function (config) { 
    var self = this, data; 

    // your default structure goes here 
    data = $.extend({ 
     name: "", 
     id : -1 
    }, config); 

    ko.mapping.fromJS(data, {}, self); 
}; 

var viewModel = function(initialData) { 
    var self = this; 

    ko.mapping.fromJS(initialData, { 
     items: { 
      create : function (options) { 
       return new YourObjectClass(options.data); 
      } 
     } 
    }, self); 

    this.AddNew = function() { 
     self.items.push(new YourObjectClass()); 
    } 
}; 

Надеюсь, это поможет.

+1

«Одно предостережение с плагином для сопоставления заключается в том, что для обновления объектов он ожидает, что эти объекты были первоначально отображены плагином. Вот краткий пример того, как это можно сделать». - Если бы я знал это раньше, это спасло бы меня много времени! – ec2011

0

Знаете ли вы поля или вам нужны они, скопированные из того, что вы получаете с сервера? Я думаю, что у вас возникнут проблемы с запуском нового списка, если это так. Вы можете просто создать шаблон и нажмите на него:

var myTemplate = { 
    name: ko.observable(), 
    phone: ko.observable() 
}; 

ViewModel.push(myTemplate); // add empty item 

Я никогда не видел вид модели будет наблюдаемую или наблюдаемый массив, то почему бы не создать его, как это?

function ViewModel() { 
    self = this; 
    self.items = ko.observableArray(); 
} 

var myViewModel = new ViewModel(); 
ko.applyBindings(myViewModel); 

$.getJSON(url, function(data) { 
    myViewModel.items.push(ko.mapping.fromJSON(data)); 
}); 
+0

Второй способ - это то, что я делаю. Мне было не очень жалко, но я имел в виду, что виртуальная машина содержит только одну коллекцию, и я точно ее заполняю. Вы правы. Я знаю свойства отдельных элементов, но я использую автоматическое сопоставление, чтобы избежать проблем с созданием шаблона для них. Если это единственный способ пойти, это прекрасно, но мне было интересно, если ko или mapping (или только JavaScript) предоставили какой-то способ «новички» объекта из ранее существующих (возможно, изучение метаданных? Cloning?). – Tallmaris