2011-08-30 3 views
6

Sto usando knockoutjs (molto nuovo ad esso) con JQuery Mobile. Ho una lista a cui leghiamo i risultati filtrati. Quando si carica i miei dati la prima volta che devo chiamareAggiorna automaticamente la visualizzazione elenco sulla modifica - knockoutjs e JQuery Mobile

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

in ordine per jQm restyling mia lista, questo funziona alla grande.

Tuttavia, quando filtro la mia lista, viene rasterizzato e perde di nuovo lo stile e non riesco a capire dove chiamare di nuovo l'aggiornamento.

mio html è la seguente:

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

mio Knockout 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'); 
} 

Sono sicuro che c'è qualcosa di molto stupido che mi manca ...

Grazie per il tuo tempo.

risposta

14

Questo problema è emerso alcune volte nei forum KO.

Un'opzione consiste nel creare un'associazione associata al proprio filteredItems ed eseguire l'aggiornamento della visualizzazione elenco.

Potrebbe apparire come:

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

Ora, si dovrebbe collocare questo sul contenitore (o realmente su qualsiasi elemento) e passare il osservabile che si desidera dipende da come:

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

Grazie, mi sono imbattuto in questo prima, ma non sono sicuro di come applicare questa associazione al mio foreach? – jimjim

+0

Davvero puoi metterlo su qualsiasi elemento, anche sul corpo. Se vuoi mantenerlo con il tuo template, allora potresti fare: 'data-bind =" template: {name: 'myTemplate', foreach: filteredItems}, jqmRefreshList: filteredItems "' –

+0

Grazie mille RP! Ha funzionato a meraviglia. BTW knockmeout è un ottimo sito. – jimjim

3

Puoi postare l'intero codice di lavoro su jsfiddle? Perché sto avendo lo stesso problema e ho provato la tua soluzione ma ancora non funziona.

[Edit]: Ok, ha funzionato bene per me in questo modo:

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

Questo mi ha salvato dal lancio del mio portatile fuori dalla finestra, grazie! –

+0

Nel mio caso stavo restituendo un ObservableArray. così in otder di usarlo, che dovevo fare: data-bind = "template: {nome: 'MyTemplate', foreach: filteredItems()}" – Adaptabi

1

Sulla base dei precedenti due risposte, qui è qualcosa di un po 'più completo. Esso consente di utilizzare containerless vincolante (cioè foreach all'interno dei commenti), e suole la questione di aggiornamento essere licenziato dopo che la pagina jQm ciclo di vita per la gestione delle eccezioni, piuttosto che un timeout:

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. 
     } 
    } 
    } 
}; 

C'è una complete worked example up on my blog. Spero possa aiutare!