2011-08-30 14 views
6

Estoy usando knockoutjs (muy nuevo) con JQuery Mobile. Tengo una vista de lista a la que debo vincular los resultados filtrados. Después de cargar los datos de mi la primera vez que tengo que llamarActualizar automáticamente la vista de lista en el cambio - knockoutjs & JQuery Mobile

$('ul').listview('refresh'); 

con el fin de personalizar la apariencia de JQM a mi lista, esto funciona muy bien.

Sin embargo, cuando filtro mi lista, se reintegra y pierde el estilo otra vez y no puedo saber dónde volver a llamar la actualización.

Mi html es el siguiente:

<p>Filter: <input data-bind="value: filter, valueUpdate: 'afterkeydown'" /></p> 
    <ul data-role="listview" data-theme="g" data-bind="template: {name: 'myTemplate', foreach: filteredItems }" /> 

Mi Knockout es JS:

var car = function (name, make, year) { 
    this.name = name; 
    this.make = make; 
    this.year = year; 
} 

var carsViewModel = { 
    cars: ko.observableArray([]), 
    filter: ko.observable() 
}; 

//filter the items using the filter text 
carsViewModel.filteredItems = ko.dependentObservable(function() { 
    var filter = this.filter(); 
    if (!filter) { 
     return this.cars(); 
    } else { 
     return ko.utils.arrayFilter(this.cars(), function (item) { 
      return item.make == filter; 
     }); 
    } 
}, carsViewModel); 

function init() { 
    carsViewModel.cars.push(new car("car1", "bmw", 2000)); 
    carsViewModel.cars.push(new car("car2", "bmw", 2000)); 
    carsViewModel.cars.push(new car("car3", "toyota", 2000)); 
    carsViewModel.cars.push(new car("car4", "toyota", 2000)); 
    carsViewModel.cars.push(new car("car5", "toyota", 2000));   
    ko.applyBindings(carsViewModel); 
    //refresh the list to reapply the styles 
    $('ul').listview('refresh'); 
} 

Estoy seguro de que hay algo muy tonto que me falta ...

Gracias tu por tu tiempo

Respuesta

14

Este problema ha aparecido en los foros de KO algunas veces.

Una opción es crear un enlace que esté vinculado a su filteredItems y ejecute la actualización de la vista de lista.

Podría verse como:

ko.bindingHandlers.jqmRefreshList = { 
    update: function(element, valueAccessor) { 
     ko.utils.unwrapObservable(valueAccessor()); //just to create a dependency 
     $(element).listview("refresh"); 
    } 
    }; 

Ahora, se pondría esto en el contenedor (o realmente en cualquier elemento) y pase el observable que usted quiere que depende de como:

<ul data-bind="jqmRefreshList: filteredItems"></ul> 
+0

Gracias, me encontré con esto antes, pero no estoy seguro de cómo aplicar este enlace a mi foreach? – jimjim

+0

Realmente puedes poner esto en cualquier elemento, incluso el cuerpo. Si desea conservarlo con su plantilla, puede hacer: 'data-bind =" template: {name: 'myTemplate', foreach: filteredItems}, jqmRefreshList: filteredItems "' –

+0

¡Muchas gracias RP! Funcionó una delicia. BTW knockmeout es un gran sitio. – jimjim

3

¿Puedes publicar todo el código de trabajo en jsfiddle? Porque estoy teniendo el mismo problema e intenté con su solución, pero todavía no funciona.

[Editar]: Ok, funcionó bien para mí de esta manera:

ko.bindingHandlers.jqmRefreshList = { 
    update: function (element, valueAccessor) { 

     ko.utils.unwrapObservable(valueAccessor()); //just to create a dependency 
     setTimeout(function() { //To make sure the refresh fires after the DOM is updated 
      $(element).listview(); 
      $(element).listview('refresh'); 
     }, 0); 
    } 
}; 
+0

Esto me salvó de tirar mi computadora portátil por la ventana, ¡gracias! –

+0

En mi caso, estaba devolviendo un ObservableArray. así que para usarlo, necesitaba hacer: data-bind = "template: {name: 'myTemplate', foreach: filteredItems()}" – Adaptabi

1

Sobre la base de las dos respuestas anteriores, aquí es algo un poco más completo. Se permite el uso sin contenedor de unión (es decir, dentro de los comentarios foreach), y las plantas el tema de la actualización de ser despedido después de la página JQM ciclo de vida por el manejo de excepciones en lugar de un tiempo de espera:

ko.virtualElements.allowedBindings.updateListviewOnChange = true; 
ko.bindingHandlers.updateListviewOnChange = { 
    update: function (element, valueAccessor) { 
    ko.utils.unwrapObservable(valueAccessor()); //grab dependency 

    var listview = $(element).parents() 
          .andSelf() 
          .filter("[data-role='listview']"); 

    if (listview) { 
     try { 
     $(listview).listview('refresh'); 
     } catch (e) { 
     // if the listview is not initialised, the above call with throw an exception 
     // there doe snot appear to be any way to easily test for this state, so 
     // we just swallow the exception here. 
     } 
    } 
    } 
}; 

Hay una complete worked example up on my blog. ¡Espero que ayude!

Cuestiones relacionadas