2012-03-04 20 views
7

Tengo una lista de archivos adjuntos en una página que se genera utilizando una llamada jQuery $.ajax y Knockout JS.Refreshing list after ajax call with Knockout JS

Mi HTML se parece a (esto es despojado de vuelta):

<tbody data-bind="foreach: attachments"> 
    <tr> 
    <td data-bind="text: Filename" /> 
    </tr> 
</tbody> 

tengo una función que obtiene la lista de los archivos adjuntos que se devuelve como respuesta JSON:

$(function() { 
    getFormAttachments(); 
}); 

function getAttachments() { 
    var request = $.ajax({ 
    type: "GET", 
    datatype: "json", 
    url: "/Attachment/GetAttachments" 
    }); 

    request.done(function (response) { 
    ko.applyBindings(new vm(response)); 
    }); 
} 

Mi vista del modelo parece:

function vm(response) { 
    this.attachments = ko.observableArray(response); 
}; 

Hay un botón de actualización que el uso puede hacer clic para volver a cargar esta lista porque respecto a mayo se han añadido los archivos adjuntos de tiempo/retirado:

$(function() { 
    $("#refresh").on("click", getAttachments); 
}); 

La prestación inicial de la lista de archivos adjuntos está muy bien, sin embargo, cuando llamo getAttachments de nuevo a través del botón de actualización, haga clic se añade la lista a (de hecho, cada elemento es duplicado varias veces).

He creado un jsFiddle para demostrar este problema aquí:

http://jsfiddle.net/CpdbJ/137

¿Qué estoy haciendo mal?

+0

Kev - nice post. Todavía estoy un poco confundido por eso. Nuevo para nocaut. Estoy teniendo problemas similares simplemente cargando un ViewModel con datos AJAX en la carga de la página. Estoy seguro de que me falta un punto pequeño pero serio. Una cosa que me confunde es que algunos tutoriales muestran 'viewmodel' como un objeto (por ejemplo' var viewmodel = {something: ko.observable()} ') y otros como una función (por ejemplo' function ViewModel() {this.something = ko.observable()} ') - alguna sugerencia? –

+0

@ one.beat.consumer - vea mi pregunta de seguimiento: http://stackoverflow.com/questions/9589419/difference-between-knockout-view-models-declared-as-object-literals-vs-functions - the la respuesta y los comentarios a continuación deberían aclarar las cosas. Recomiendo gastar $ 25 y ver esto: http://www.pluralsight-training.net/microsoft/Courses/TableOfContents?courseName=knockout-mvvm – Kev

+0

Voy a ver su otra pregunta; gracias. Tengo una suscripción de pluralsight y la he visto 2-3 veces ... apenas rascan la superficie y gran parte de ella es vieja ahora que 2.0 está fuera, estaban usando 1.2 o 1.3 beta ... –

Respuesta

10

Aquí hay un violín que arregla su muestra. Tu mayor problema fue que llamaste 'applyBindings' varias veces. En general, invocará applyBindings en la carga de la página y luego la página interactuará con el modelo de visualización para hacer que Knockout restaure porciones de su página.

http://jsfiddle.net/CpdbJ/136

html

<table> 
    <thead> 
     <tr><th>File Name</th></tr> 
    </thead> 
    <tbody data-bind="foreach: attachments"> 
     <tr><td data-bind="text: Filename" /></tr> 
    </tbody> 
</table> 
<button data-bind="click: refresh">Refresh</button> 

Javascript

$(function() { 
    var ViewModel = function() { 
    var self = this; 

    self.count = 0; 
    self.getAttachments = function() { 
     var data = [{ Filename: "f"+(self.count*2+1)+".doc" }, 
        { Filename: "f"+(self.count*2+2)+".doc"}]; 
     self.count = self.count + 1; 
     return data; 
    } 

    self.attachments = ko.observableArray(self.getAttachments()); 

    self.refresh = function() { 
     self.attachments(self.getAttachments());   
    } 
    }; 

    ko.applyBindings(new ViewModel()); 
}); 

-

También es posible que desee ver en el plugin de mapeo - http://knockoutjs.com/documentation/plugins-mapping.html. Puede ayudarlo a transformar JSON en Modelos de Vista. Además, puede asignar una propiedad para que sea la "clave" de un objeto ... esto se usará para determinar objetos antiguos frente a nuevos en mapeos posteriores.

Aquí es un violín que escribió hace un tiempo para demostrar una idea similar:

http://jsfiddle.net/wgZ59/276

NOTA: Yo uso la 'actualización' como parte de las reglas de asignación, pero sólo para que pueda conectarse a la consola. Solo necesita agregar esto si desea personalizar cómo el complemento de asignación actualizó los objetos.

+0

¿Cómo funcionaría esto si decir que no tenía datos, y tengo que llamar a un método Ajax y es un GET? – Vyache

+0

Simplemente cambie la llamada getAttachments para realizar la llamada AJAX, y en la devolución de llamada establezca los resultados directamente en la matriz observable de los archivos adjuntos. Actualizar simplemente llamaría a self.getAttachments(). los archivos adjuntos se inicializarán vacíos, y luego podrá llamar inmediatamente a self.getAttachments() para realizar la primera llamada AJAX. Una vez que la devolución de llamada establece los resultados, Knockout se encargará de actualizar su UI. –

+0

Hmm, por alguna razón no puedo actualizar mis datos con este método, vea mi pregunta: http://stackoverflow.com/questions/21558075/how-do-i-update-my-model-using-ajax-and -mapping-plugin – Vyache