2011-08-30 14 views
6

Używam knockoutjs (bardzo nowego) z JQuery Mobile. Mam widok listy, do którego wiążę filtrowane wyniki. Po załadowaniu moich danych po raz pierwszy muszę zadzwonić pod numerAutomatyczne odświeżanie widoku listy przy zmianie - knockoutjs i JQuery Mobile

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

, aby JQM mógł zmienić swoją listę, działa to znakomicie.

Jednak po odfiltrowaniu mojej listy, jest ona ponownie zgłaszana i ponownie traci styl i nie mogę ustalić, od której strony należy ponownie odświeżyć.

Moje html wygląda następująco:

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

My Knockout JS jest:

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

Jestem pewien, że coś jest bardzo głupie, że mi brakuje ...

Thank za twój czas.

Odpowiedz

14

Ten problem pojawił się kilka razy na forach KO.

Jedną opcją jest utworzenie powiązania związanego z Twoim filteredItems i uruchomienie odświeżenia listy.

To może wyglądać następująco:

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

Teraz, by umieścić to na opakowaniu (albo naprawdę na każdy element) i przechodzą w zaobserwować, że chcesz to zależy od jak:

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

Dzięki, natknąłem się na to wcześniej, ale nie jestem pewien, jak zastosować to powiązanie z moim foreach? – jimjim

+0

Naprawdę możesz umieścić to na dowolnym elemencie, nawet na ciele. Jeśli chcesz zachować go za pomocą szablonu, możesz zrobić: 'data-bind =" template: {nazwa: 'myTemplate', foreach: filteredItems}, jqmRefreshList: filteredItems "' –

+0

Wielkie dzięki! Pracował uczta. BTW Knockmeout to świetna strona. – jimjim

3

Czy możesz umieścić cały działający kod na jsfiddle? Ponieważ mam ten sam problem i próbowałem Twojego rozwiązania, ale nadal nie działa.

[Edit]: Ok, to działało w porządku dla mnie tak:

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

To uratowało mnie przed wyrzuceniem mojego laptopa przez okno, dzięki! –

+0

W moim przypadku zwróciłem ObservableArray. w związku z tym potrzebowałem: data-bind = "template: {nazwa:" myTemplate ", foreach: filteredItems()}" – Adaptabi

1

Opierając się na poprzednich dwóch odpowiedzi, tutaj jest coś trochę bardziej kompletne. To pozwala na użycie containerless wiązania (tj foreach w komentarzach) i podeszwy kwestia odświeżenia wyrzuceniu po cyklu strona jQM przez obsługę wyjątków zamiast 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. 
     } 
    } 
    } 
}; 

Jest complete worked example up on my blog. Mam nadzieję, że pomaga!

Powiązane problemy