2012-11-05 19 views
22

Zasadniczo mam obserwowalną tablicę, a wartości dla każdego elementu nie są obserwowalne. Oznacza to, że po zmianie wartości elementu interfejs użytkownika w pętli foreach obiektu obserwowalnego nie jest odpowiednio aktualizowany.Odśwież observableArray, gdy elementy nie są obserwowalne.

Oznacza to masywną zmianę, jeśli muszę ustawić je tak, aby były obserwowalne, więc czy istnieje sposób na ręczne odświeżenie interfejsu użytkownika lub obserwowalnego foreach?

Odpowiedz

46

Tak można nazwać valueHasMutated funkcję dla swojej tablicy:

yourArray.valueHasMutated(); 

EDIT: skrzypce

self.refresh = function(){ 
    var data = self.array().slice(0); 
    self.array([]); 
    self.array(data); 
}; 

Tu pracuje: Jeśli najpierw nie pomoże można zrobić 'brudnej' odświeżanie : http://jsfiddle.net/vyshniakov/FuEy6/2/

+5

To nadal nie aktualizuje dla mnie interfejsu użytkownika – user1166905

+1

valueHasMutated działało dobrze dla mnie. – Edyn

+7

dlaczego trzeba wykonać kopię tablicy, wywołując slice (0)? działa również i jeszcze lepiej 'var data = self.array(); self.array (null); self.array (dane);' –

5

Skończyło się na tym, że wykorzystałem brudne podejście z góry, ale zrobiłem to, aby wszystkie moje obserwowalne macierze miały tę funkcjonalność.

Funkcja valueHasMutated nie działała dla mnie. Jego rodzaj lame, cała lista musi zostać zaktualizowana. Lub w moim przypadku znajdź sposób na rozszerzenie wtyczki mapowania ko w celu wypełnienia obserwowalnych tablic z obserwowalnymi obiektami.

+2

'var data = this()/* slice() * /; this (null), this (data);' będzie działać równie dobrze i jeszcze szybciej –

16

Gdy masz tablicę obserwowalną z nieobserwowalnymi elementami i niektóre właściwości jednego z elementów w tablicy zmian jeśli chcesz odświeżyć tylko ten element, można użyć indexOf i splice coś takiego:

var changedIdx = obsArray.indexOf(changedItem); 
obsArray.splice(changedIdx , 1); // removes the item from the array 
obsArray.splice(changedIdx , 0, changedItem); // adds it back 

Co to robi, szuka elementu w tablicy, usuwając je i wkładając ją do tyłu. Po ponownym wstawieniu element jest ponownie powiązany z nowymi wartościami.

Jeśli podoba Ci się to rozwiązanie, można rozszerzyć funkcjonalność wszystkie Ko obserwowalnych tablic, jak poniżej:

ko.observableArray.fn.refresh = function (item) { 
    var index = this['indexOf'](item); 
    if (index >= 0) { 
     this.splice(index, 1); 
     this.splice(index, 0, item); 
    } 
} 

Następnie, po zmianie elementu tablicy, po prostu trzeba zrobić to wezwanie:

obsArray.refresh(changedItem); 

Jeśli masz wiele elementów macierzy dostaniesz lepszą występ względem dirty odświeżyć Artem Vyshniakov, które aktualizacje powiązań dla wszystkich elementów w tablicy, a nie tylko dla jednej zmienionej .

Uwaga: valueHasMutated, appart przed nieudokumentowane (oraz do użytku wewnętrznego, jak sądzę), tylko sprawdza, czy sama tablica uległa zmianie, nie, jeśli nie obserwowalne elementy w tablicy uległy zmianie, więc nie robi” t działa. To znaczy. wykrywa tylko, czy dodano elementy do tablicy, usunięto elementy z tablicy, zmieniono elementy tablicy za pomocą nowych, różnych elementów lub zmieniono kolejność elementów. Ale nie sprawdza, czy same elementy uległy zmianie

+0

piękne, przydatne rzeczy dzięki – Andrew

+0

Zauważ, że 'obsArray.indexOf() 'szukaj elementu po prostu dopasowującego wartość za pomocą' === 'ale w javascript' {'x': 'X'} === {'x': 'X'} 'return false –

+0

Masz rację. Jednak w tym scenariuszu ** masz odwołanie do elementu tablicy, który chcesz mofidy **. Nie modyfikujesz obiektu, który wygląda jak obiekt w tablicy, ale obiekt w tablicy. Tak więc, używając 'indexOf' znajdzie go. Jeśli zmieniłeś obiekt, który nie jest w tablicy, musiałbyś zamienić obiekt w tablicy na nowy, który różni się od zmieniania właściwości ** elementu w tablicy ** i powiadamiania, że ​​się zmienił, Drugi przypadek jest zupełnie inny. – JotaBe

0

Znalazłem proste rozwiązanie, zastępując cały obiekt w tablicy.

W tym przykładzie parametr ix jest indeksem, Oline jest aktualizowany obiekt i oVM.objProps.linie zawiera tablicę. Rozwiązanie działało jak mistrz.

/* This contortion causes the computed function to fire because 
* we have replaced the entire line object. 
*/ 
function forceRefresh(ix,oLine) { 
    var oVM = pme.getVM(); 
    oLine = JSON.parse(JSON.stringify(oLine)); 
    oVM.oObjProp.lines[ix] = oLine; 
} 
Powiązane problemy