2015-05-12 25 views
9

Moim celem jest napisanie aplikacji SAPUI5 Fiori z obsługą routingu. Jednym celem jest uzyskanie łatwych adresów URL. Na przykład w wiadomości e-mail, np. "Zatwierdź: link". Łącze jest adresem URL dopasowanym przez moją konfigurację rountingową, np. index.html#/applicants/8.Routing w SAPUI5: Jak zaimplementować przekazanie adresu URL? Dane modelu nie zostały zainicjowane

Używam typowej aplikacji typu sap.m.SplitApp. Kliknięcie elementu listy w widoku głównym powoduje zmianę adresu URL na index.html#/applicants/[id of entry in JSON]. Mogę kliknąć na liście, moje zdefiniowane trasy są dopasowywane, a aplikacje ładują dane (wnioskodawcy) zgodnie z oczekiwaniami.

Jednak tutaj pojawia się moje pytanie, to nie działa, gdy bezpośrednio korzystasz z adresu URL, powiedzmy wklejając [my url]/index.html#/applicants/8 do mojej przeglądarki. Aplikacja zostanie uruchomiona, ale nie załadowano danych szczegółowych. Muszę ponownie kliknąć na inny element listy, aby uzyskać dane.

W rzeczywistości kontroler jest wywoływany podczas przekazywania adresu URL, ale wygląda na to, że model nie jest inicjowany i nie jest zdefiniowany. Mój model JSON jest związany z funkcją createContent moich Component.js

// Aktualizacja 2015-05-14 Problemy wydaje się wokół funkcji getData(). Mam model, ma wpisy, ale getData() zwraca undefined po raz pierwszy moja aplikacja jest ładowana. Ostatnio czytałem, że getData() jest przestarzałe. Jak mam poprawić moje kodowanie poniżej?

// Component.js 
ui5testing.Component.prototype.createContent = function(){ 
    // create root view 
    var oView = sap.ui.view({ 
    id : "app", 
    viewName : "ui5testing.view.Main", 
    type : "JS", 
    viewData : { 
     component : this 
    } 
    var oModel = new sap.ui.model.json.JSONModel("model/mock_applicants.json"); 
    oView.setModel(oModel); 
    [...] 
    return oView; 
}); 
// Master controller 
handleApplicantSelect : function (evt) { 
    var oHashChanger = sap.ui.core.routing.HashChanger.getInstance(); 
    var context = evt.getParameter("listItem").getBindingContext(); 
    var path = context.getPath(); 
    var model = this.getView().getModel(); 
    var item = model.getProperty(path); 
    oHashChanger.setHash("applicants/" + item.id); 
}, 

// Detail controller 
onInit: function() { 
    this.router = sap.ui.core.UIComponent.getRouterFor(this); 
    this.router.attachRoutePatternMatched(this._handleRouteMatched, this); 
}, 

_handleRouteMatched : function(evt){   
    var objectId = evt.getParameter("arguments").id; 
    var model = this.getView().getModel(); 
    var data = model.getData()["applicants"]; 
    var pathId; 

    if (data) { 
     for (var i = 0; data.length; i++) { 
      if (objectId == data[i].id) { 
       pathId = i; 
       break; 
      } 
     } 

     var sPath = "/applicants/" + pathId; 

     var context = new sap.ui.model.Context(model, sPath) 
     this.getView().setBindingContext(context);    
    } 
}, 
+1

to jest wywołanie createContent? Jak i gdzie ustawiasz model? this.getView(). getModel(); nie brzmi jak dobry pomysł, gdy model nie jest już dołączony do danego widoku PRZED. – cschuff

+0

Przepraszam, już to naprawiłem. Zobacz aktualizację. – SDD64

+0

Przepraszam raz jeszcze, po refaktorze problem pojawił się ponownie. Model jest ustawiony w Compoent.js createContent(). Ustaw na główny widok główny. – SDD64

Odpowiedz

4

Po ustaleniu, że getData() po raz pierwszy zwraca wartość undefined, co oznacza, że ​​dane modelu nie zostały jeszcze załadowane. Tak więc można skorzystać z metody attachRequestCompleted modelu & wywoływania zdarzenia z komponentu & nasłuchiwania tego zdarzenia w kontrolerze szczegółów, aby zapewnić, że procedura routerPatternMatched() zostanie wykonana dopiero po załadowaniu danych.

//Component.js

var oModel = new sap.ui.model.json.JSONModel("model/mock_applicants.json"); 

oModel.attachRequestCompleted(jQuery.proxy(function(){ 
    this.fireEvent("MockDataLoaded"); // fireEvent through component 
},this)); 

oView.setModel(oModel); 

// Szczegóły kontroler

onInit : function(){ 

this.router = sap.ui.core.UIComponent.getRouterFor(this); 

var oComponent = this.getOwnerComponent(); 

oComponent.attachEvent("MockDataLoaded",jQuery.proxy(function(){ 
    this.router.attachRoutePatternMatched(this._handleRouteMatched, this); 
},this)); 

} 

Albo najprostszy & ale brudny sposób byłoby zrobić synchroniczne żądania zamiast żądania asynchronicznego ładowania danych .

var oModel = new sap.ui.model.json.JSONModel(); 

oModel.loadData(""model/mock_applicants.json",{bAsync:false}); 

oView.setModel(oModel); 
+0

Bardzo pomocna odpowiedź, dziękuję! Przyznam, że znalazłem sposób używania 'attachRequestCompleted' przeze mnie. Jednak Twoje rozwiązanie wygląda na bardziej przejrzyste. Jedno pytanie: czy można użyć SAPUI5 'EventBus' zamiast' jQuery.proxy() '? – SDD64

+1

możesz użyć EventBus zamiast wypalania wydarzeń! Powodem używania jQuery.proxy jest to, że wartość "this" w procedurze obsługi zdarzeń będzie inna. Spróbuj usunąć jQuery.proxy z funkcji obsługi zdarzenia i spróbuj ustalić wartość "this". – sakthi