2012-06-25 13 views
6

Pracuję na systemie Android z Jquery Mobile z Phonegap przy użyciu Knockout do ładowania danych.Knockout refresh obserwujArray w html

Dostaję dane w porządku i ładuję je na stronę html zgodnie z powiązaniem danych foreach, które mam na znacznikach.

Kiedy chcę odświeżyć dane, po prostu tego nie robię. Zwraca on tylko html bez danych wiązanych lub nie znaleziono wyjątku miotania dom Moje applyBinding dzieje się wewnątrz zdarzenia stronicowania strony.

Opublikowałem prosty przykład opisujący problem na moim SkyDrive - http://sdrv.ms/LpUdLt Jest to publiczny przykład odwzorowujący problem. Model viewmodel posiada tablicę zawierającą tablicę. odświeżony z wartościami losowymi. próbuje przeładować stronę w jquery mobile z ładowaniem strony changup z nowymi danymi, naciskając przycisk na pasku nawigacyjnym kończy się niepowodzeniem z błędem obiektu dom. Zgadzam się, że nie powinienem tworzyć instancji maszyny wirtualnej dla każdej strony, ale nie mogę znaleźć sposobu na jej wdrożenie, aby dane zostały ponownie przesłane na html.

//indexPage.js 
    var wAViewModelInst ; 
    var viewPageIndexContent; 
    $('#pageIndex').live('pagecreate', function (event) { 
     viewPageIndexContent = document.getElementById("pageIndexContent"); 
     wAViewModelInst = new WAViewModel(true); 
     ko.applyBindings(wAViewModelInst, viewPageIndexContent); 

     waHeaderVM.refreshContentData = function() { 

       // wAViewModelInst.updateRowList(); 
       // ko.cleanNode(viewPageIndexContent); 
       // viewPageIndexContent = document.getElementById("pageIndexContent"); 
       //wAViewModelInst = new WAViewModel(true); 
      //ko.applyBindings(wAViewModelInst, viewPageIndexContent); 
       $.mobile.changePage("index.html", { allowSamePageTransition: true, reloadPage: true }); 
       $.mobile.hidePageLoadingMsg(); 
     } 
    } 

    //WAViewModel 
    self.WARowList = ko.observableArray(); 
    self.updateRowList = function() { 
     self.WARowList(self.GetWA()); 
    } 
    //tried the exteding 
    //ko.observableArray.fn.WARowListUpdate = function() { 
    // //create a sub-observable 
    // this.hasItems = ko.observable(); 

    // //update it when the observableArray is updated 
    // this.subscribe(function (newValue) { 
    //  this.hasItems(newValue && newValue.length ? true : false); 
    // }, this); 

    // //trigger change to initialize the value 
    // this.valueHasMutated(); 

    // //support chaining by returning the array 
    // return this; 
    //};    

Czy istnieje sposób aktualizacji html po pierwszym renderowaniu?

dodając kod HTML:

<div id="pageIndex" data-role="page" data-transition="flip" data-theme="e" data-dom-cache="true"> 
    <div id="indexHeader" data-role="header" data-theme="e"> 
     <div data-role="navbar" data-iconpos="right"> 
      <ul> 
       <li><a href="login.html" data-role="tab" data-icon="back" data-bind="click: loadingHandler" 
        class="brighter-text">חזרה</a></li> 
       <li><a href="#" data-role="tab" data-icon="refresh" data-bind ="click: refreshContentData" >רענן</a></li> 
       <li><a href="researchEvent.html" data-role="tab" data-icon="check" id="navBarResearchEventPage" data-bind="click: loadResearchEvent" class="brighter-text">ביצוע חקר</a></li> 
       <li><a href="#" data-role="tab" data-icon="grid" class="ui-btn-active brighter-text"> 
        סידור עבודה</a></li> 
      </ul> 
     </div> 
    </div> 
    <div id="pageIndexContent" data-role="content" data-theme="e" style="padding-bottom: 52px; 
     height: 570px;"> 
     <h2 data-bind="text:Title" class="brighter-text" style="font-size:22pt;"> 
     </h2> 
     <div data-bind="foreach: WARowList" style="width: 99%; text-align: center"> 
      <div> 
       <table style="float: right; width: 20%; height: 60px;" cellpadding="0" cellspacing="0"> 
        <tr data-bind="visible : FirstRow " style="height: 31px;"> 
         <th class="AlignedHeader"> 
          <label> 
           שעה/שילוט</label> 
         </th> 
        </tr> 
        <tr data-bind="style: { backgroundColor: Odd() ? '#8CC63F' : '#AFC493' }"> 
         <td style="width: 20%;" data-bind="style: { backgroundColor: IsNew() ? 'yellow' : 'transparent' }"> 
          <input type="button" data-bind="click: ShowSampleDetails, value: ShilutTime , jQueryButtonUIEnableDisable:$data" 
           data-icon="plus" data-iconpos="right"/> 
         </td> 
        </tr> 
       </table> 
       <table style="height: 60px; width: 80%; background-color: #8CC63F;" data-bind="style: { backgroundColor: Odd() ? '#8CC63F' : '#AFC493' }" 
        cellpadding="0" cellspacing="0"> 
        <thead data-bind="if : FirstRow"> 
         <tr data-bind="foreach: CellList"> 
          <th class="AlignedHeader"> 
           <label data-bind="text: Date"> 
           </label> 
          </th> 
         </tr> 
        </thead> 
        <tbody> 
         <tr data-bind="foreach: CellList"> 
          <td style="width: 11.5%;"> 
           <div data-bind="visible:IsPopulated "> 
            <div data-bind="visible: HasDrivers"> 
             <input type="button" data-role="button" data-bind="click: ShowBusDriverList.bind($data , $root) , jQueryButtonUIEnableDisable: $data " 
              data-icon="search" data-iconpos="right" value="נהגים" class="brighter-text" /> 
            </div> 
            <div data-bind="visible: !HasDrivers()"> 
             <input type="button" data-role="button" id="btnNoDriver" disabled="disabled" data-icon="info" 
              data-iconpos="right" value="אין נהג" class="brighter-text" /> 
            </div> 
           </div> 
           <div data-bind="visible: !IsPopulated"> 
           </div> 
          </td> 
         </tr> 
        </tbody> 
       </table> 
      </div> 

i tak dalej ..

funkcja GetWA zwracającą observableArray listy warow. po raz pierwszy problem polega na ponownym utworzeniu obiektu dom. element dom jest zanieczyszczona i nie ko ..

Próbowałem odpowiedź Luffy:

var lVM = new loginViewModel(); 
var footerViewModelLogin = { 
     IsOnline: ko.observable(globalContext.Network()), 
     IsSync: ko.observable(globalContext.Sync()) 
    }; 
$('#login').live('pagecreate', function (event) { 


    viewLoginContent = document.getElementById("loginContent"); 

    ko.applyBindingsToNode(viewLoginContent, lVM); 


    viewLoginFooter= document.getElementById("footerLogin"); 

    ko.applyBindingsToNode(viewLoginFooter, footerViewModelLogin); 


}); 


$('#login').live('pagehide', function (event, ui) { 
    $.mobile.hidePageLoadingMsg(); 

}); 



function loginViewModel() { 
    var self = this; 

    try { 

     self.userName = ko.observable(""); 
     self.password = ko.observable(""); 
     self.message = ko.observable(""); 

     self.CleanGlobalContext = function() { 
      ... 

     }; 

     self.Validate = function() { 

      ... 

     }; 
    } 
    catch (e) { 
     if (IsDebug) alert("GlobalContext.prototype.SetMapOverlay " + e.message); 
     if (typeof (console) != 'undefined' && console) console.log("GlobalContext.prototype.SetMapOverlay "  + e.message); 
    } 
} 

ko.applyBindings(lVM); 
ko.applyBindings(footerViewModelLogin); 

nokaut nie bez elementu predefiniowane zdarzenia do wiązania.

+0

Czy możesz pokazać nam nieco więcej kodu, takiego jak HTML lub metoda GetWA? Kiedy mówisz "zwraca tylko pusty HTML", co jest wywoływane, które zwraca pusty HTML? – CodeThug

+0

pytanie, czy istnieje sposób ponownego zastosowania wiązań? ponowne zainicjowanie obiektu obserwacyjnegoArray w widokuModel nie reorganizuje i nie odświeża widoku. –

+0

Poprawiłem wpis - nie zwraca emty html - zwraca HTML bez informacji o powiązaniu danych odświeżonego viewmodelu. –

Odpowiedz

0

Tak można ponownie zastosować wiązania z funkcją ko.applyBindingsToNode do określonego elementu dom.

Sprawdź te przykłady

  1. http://jsfiddle.net/rniemeyer/gYk6f/ ---> Z szablonów
  2. http://jsfiddle.net/rniemeyer/BnDh6/ ---> Z danych - parę wartości
+0

Spróbuję, ale problem polegający na tym, że jest to obserwowalna tablica z zagnieżdżonymi obserwowalnymiArrays, czy to jest to samo? –

+0

Nie przeszło przez wiązanie stosu bez zdefiniowanego elementu –

2

nie mam rozumiesz dobrze, masz trudności. Jednak nie rozumiem, dlaczego musisz ponownie zastosować wiązania. Zauważ, co następuje:

  1. Jeśli zmienisz tablicę obserwowalną, potrzebne szablony zostaną ponownie utworzone, aby zaktualizować spójnie interfejs użytkownika. Jednak musisz zaktualizować tablicę obserwowalną za pomocą obserwowalnych funkcji tablicowych lub przekazując obserwowalną nową tablicę: obs (newArray).
  2. Jeśli musisz wykonać akcje po ponownym renderowaniu ko, musisz po prostu użyć parametrów afterRender lub afterAdd szablonu wiążącego
  3. , jeśli dodasz nowy kod mobilny jquery, musisz go sparsować po utworzeniu go inaczej jquery mobile nie działa ... znowu możesz to zrobić w funkcji afterRender.
  4. jest problematyczne ładowanie html zawierającego wiązanie ajax ko przez ajax. Właściwe podejście polega na stworzeniu tej treści jako szablonu, który renderujesz natychmiast (nie w przypadku ajax). Następnie przesyłasz zapytanie do serwera, aby uzyskać nową zawartość json. Następnie możesz utworzyć instancję szablonu za pomocą na przykład wiązania.
+0

1. Ponownie wprowadziłem tablicę obserwowalną z nowymi danymi, ale Potrzebne szablony nie są ponownie tworzone, aby zaktualizować spójnie interfejs użytkownika, faktycznie po prostu pokazuje mi html bez danych w ogóle 2.afterRender Potrzebuję utworzyć bindingHandler aktualizacji dla obserwowalnego Array? 3. Czas na nawigację między jqm strony, po pierwszym applyBinding nie można ponownie zainicjować elementu "dom", to jest problem .. –

+0

może gdzieś jest jakiś błąd ... Używam wielu szablonów ... nigdy nie miałem podobnego problemu ... jednak kiedy używam jquery mobile z nokautem, wstępnie ładuję wszystkie strony i komunikuję się z serwerem tylko w jsonie ... pobrałem twój kod ... pozwól mi Spójrz. –

+0

Wstępne ładowanie byłoby najlepszą opcją, gdybym mógł odświeżyć dane ko w nim. –

0

Roztwór dodać afterRender w tabeli danych foreach-wiązania. as - zasugerował Francesco Abbruzzese. Żądanie ajax zostało zmienione na async: false though. Za każdym razem, gdy aktualizuję listę, wykonuję pewne polecenie data-bind = "click: updateRowList", które aktualizuje tabelę. Wielkie dzięki dla Elada Katza za pomoc w bounty.

+0

Witam, myślałem, że rozwiązaniem będzie użycie afterRender, które zasugerowałeś. Niemniej jednak . usunąłem afterRender i sama aplikacja aktualizuje się. Problem polegał na usunięciu wartości z istniejącej listy i ponownym zainicjowaniu wartości nowymi danymi. –