2012-08-30 24 views
6

Estoy seguro de que esta será una respuesta fácil para alguien. Tengo el siguiente modelo de vista:eliminar de observableArray- knockoutjs

@{ 
    var initialData = new JavaScriptSerializer().Serialize(Model); 
} 
var data = @Html.Raw(initialData); 
function ViewModel(data) { 
    var self = this; 
    self.Name = ko.observable(data.Name); 
    self.Items = ko.observableArray(data.Items); 
    self.addItem = function() { self.Items.push(""); }; 
    self.removeItem = function(data) { self.Items.remove(data); } 
} 
$(document).ready(function() {ko.applyBindings(new ViewModel(data)); }); 

Y los próximos:

<div> 
    Name: <span data-bind="text: Name"></span> 
</div> 
<div> 
    Items: <button data-bind="click: addItem">Add Item</button> 
</div> 
<div> 
    <table> 
     <tbody data-bind="template: { name: 'itemTemplate', foreach: Items }"></tbody> 
    </table> 
</div> 
<script type="text/html" id="itemTemplate"> 
    <tr> 
     <td> 
      <input data-bind="value: $data" /> 
      <a href="#" data-bind="click: function() {$parent.removeItem($data)}">Remove Item</a> 
     </td> 
    </tr> 
</script> 

todo parece funcionar correctamente a excepción de removeItem. Cuando se agreguen nuevas filas y se haga clic en "Eliminar elemento" en una nueva fila vacía, todas las nuevas filas se eliminarán con ella. He visto un montón de tutoriales knockout tratando de hacer que esto funcione, y mi método parece ser un intento válido, pero obviamente ... Me falta algo. ¿Alguna sugerencia?

Respuesta

14

La función remove de un array observable recorre el conjunto y elimina cualquier elemento que coincida con el valor que se le haya pasado. En su caso, solo está tratando con cadenas y verá que todas las nuevas (sin ningún valor) coincidirán con "".

Hay un par de formas de manejarlo:

  • se puede tratar con objetos en lugar de sólo cadenas como { value: ko.observable("") }. Luego, cuando pase $data, solo eliminará el elemento real que coincida con esa referencia de objeto. Si su valor no es observable y son los datos en sí (no una propiedad), entonces sus escrituras en realidad no volverán a su modelo de vista.

  • si eso no funciona para su escenario, entonces podría eliminar elementos basados ​​en el índice ($index) mediante el empalme.

que probablemente hacerlo como: http://jsfiddle.net/rniemeyer/N3JaW/

También tenga en cuenta que el event (click es una envoltura para event) vinculante pasará los datos actuales como primer argumento al controlador, por lo que puede simplificar su enlace al click: $parent.removeItem.

actualización: Aquí hay varias maneras que usted puede controlar la forma en que el objeto se convierte en JSON:

  • ko.toJSON pasa su 2ª y 3ª argumentos a JSON.stringify. El segundo arg permite ejecutar una función para reemplazar potencialmente los valores como se describe en here. Aquí hay una muestra que verifica si la clave es un número (elemento de matriz) y tiene una propiedad value. Si es así, simplemente devuelve la cadena en lugar del objeto. http://jsfiddle.net/rniemeyer/N3JaW/1/

  • Si utiliza una función constructora para sus objetos, a continuación, se puede reemplazar la función toJSON como se describe here. Aquí está su muestra con esta funcionalidad: http://jsfiddle.net/rniemeyer/N3JaW/2/

  • Otra técnica que se puede utilizar es mantener un observable calculado que tiene el "buen" valor. Aquí está la muestra: http://jsfiddle.net/rniemeyer/N3JaW/3/. En este caso, Items es un observable calculado que devuelve el valor limpio. Items.asObjects contiene la versión de objeto de sus valores. Cuando se convierte a JSON, la parte asObjects se cae naturalmente cuando Items se convierte a JSON.Si solo necesita este conjunto "bueno" al convertir a JSON, las otras opciones son mejores para el rendimiento (solo se calculan cuando desea enviarlo).

+0

Me gusta mucho su enfoque en jsfiddle, pero no mencioné que tendré que volver a publicar este modelo en el servidor. Eso significa que 'Items' necesita ser una cadena []. Entonces supongo que eso significa que debería ir a la ruta de $ index, ¿correcto? –

+0

No necesariamente. Hay varias formas de garantizar que la salida JSON vuelva al estado que desea. Le daré alguna información a la respuesta. –

+0

Te daría dos ups si pudiera. Respuesta muy útil. –

Cuestiones relacionadas