Kommunikation zwischen Rich-UI-Handlern ohne Infobus

Eine Möglichkeit, eine Anwendung zu organisieren, besteht darin, die Benutzerinteraktion, wie sie durch einen Rich-UI-Handler dargestellt wird, und die Back-End-Verarbeitung von Geschäftsdaten, wie sie durch einen zweiten Rich-UI-Handler dargestellt wird, voneinander zu trennen. In diesem Abschnitt werden einige Mechanismen neben dem Infobus aufgezeigt, durch die ein Handler mit einem anderen Handler kommunizieren kann.

Daten aus dem einbettenden Handler durch einen Funktionsaufruf übertragen

Im einfachsten Fall kann der einbettende Handler eine Funktion im eingebetteten Handler aufrufen:
Handler EmbeddingHandler type RUIHandler 
   { onConstructionFunction = onConstructionFunction }

   embeddedHandler EmbeddedHandler;
   
   function onConstructionFunction()
      myString STRING = "Received from somewhere";
      embeddedHandler.function01(myString);
   end
end 

Stellvertreter verwenden

Eine weitere Möglichkeit besteht darin, den eingebetteten Handler zu veranlassen, eine Funktion im einbettenden Handler aufzurufen: In diesem Fall aktualisiert der einbettende Handler den Wert, der einem Stellvertreter ('Delegate') im eingebetteten Handler zugeordnet ist. Ein Stellvertreter ist eine Variable, die auf eine Funktion eines bestimmten Typs verweist, das heißt, die Variable stellt den Zugriff auf eine Funktion bereit, die eine bestimmte Gruppe von Merkmalen besitzt.

Die Beziehungen können anhand eines Beispiels veranschaulicht werden. Betrachten Sie den folgenden EGL-Stellvertreterabschnitt, der eine Funktion definiert, die keine Parameter und keinen Rückgabewert hat:
delegate switchPart() end

Das nächste Beispiel zeigt, wie zwischen zwei Webseiten umgeschaltet werden kann. In diesem Beispiel hat der eingebettete Handler den Namen 'Page2' und deklariert den Stellvertreter mit dem Namen 'switch':

handler Page2 type RUIHandler { onConstructionFunction = myFirstFunction, 
                                initialUI = [content] }
	
	content Box{children = [secondLabel, button], columns = 1};
	secondLabel TextLabel{text = "page2!"};
	button Button{text="switch back to first page", onClick ::= switchToFirst};
	
	//Deklaration eines Stellvertreters
	switch switchPart{};
	
	function myFirstFunction()
	end
	
	function switchToFirst(e Event in)
		 switch();  
	end	
end

Die Frage ist, welche Logik ausgeführt wird, wenn 'switch()' innerhalb von 'switchToFirst' aufgerufen wird. Die Antwort findet sich im einbettenden Handler 'Page1', der dem Stellvertreter eine eigene Funktion zuordnet:

handler Page1 type RUIHandler 
  { onConstructionFunction = myFirstFunction, initialUI = [page] }
	
	 page Box{ columns = 1, children = [firstLabel, button]};
	 firstLabel TextLabel{text = "page1!"};
	 button Button{text = "switch to page 2", onClick ::= switchTo2};	
	
	 page2 Page2{};	
		
	 function myFirstFunction()
	    page2.switch = switchBack;  
	 end
	
	 function switchTo2(e Event in)
		  page.children = [page2.content];
	 end			
	
	 function switchBack()
		   page.children = [firstLabel, button];
   end
end

Mit Stellvertretern zu einer beliebigen von mehreren Seiten navigieren

Eine Erweiterung des vorherigen Beispiels ist die Definition eines Seitenhandlers (hier mit dem Namen 'MainHandler'), der die nachfolgende Navigation des Benutzers zu einer von mehreren Webseiten steuert. Hier wird wiederum ein seitenweiser Ereignisablauf erstellt, was für Webanwendungen der traditionelle Ansatz ist. Sie können mit einem Ansatz wie diesem beginnen, wobei zu beachten ist, dass Rich-UI die Möglichkeit bietet, Teile einer Webseite als Antwort auf ein Laufzeitereignis zu aktualisieren.

In diesem Beispiel akzeptiert der Stellvertreterabschnitt eine Zeichenfolge und hat keinen Rückgabewert:
delegate SwitchToPagePart( TargetPage STRING in) end

Hier sind drei Rich-UI-Handler beteiligt. Die folgende Abbildung zeigt die Ausgabe des ersten Handlers mit dem Namen 'ButtonHandler', der die verfügbaren Optionen anzeigt:

Ausgabe von ButtonHandler

Beachten Sie beim Durchsehen des Codes, dass switchFunction ein Stellvertreter ist und das seine Aufrufe auf Logik verweisen, die sich in 'MainHandler' befindet, der später gezeigt wird:
handler ButtonHandler type RUIHandler{initialUI = [button1, button2, button3]}
   switchFunction SwitchToPagePart;
   button1 Button{text = "Go To Main Page", onClick::= toMain};
   button2 Button {text = "Stay Here"};
   button3 Button{text = "Go to TextField", oncLick::=toText};
   
   function toMain(e Event in)
		   switchFunction("MainHandler");
   end

   function toText(e Event in)
		   switchFunction("TextFieldHandler");
   end
end

Das folgende Beispiel zeigt die Ausgabe des zweiten Handlers mit dem Namen 'TextFieldHandler':

Ausgabe von TextFieldHandler

Beachten Sie beim Durchsehen des Codes, dass dieser Rich-UI-Handler auch einen Stellvertreter deklariert, der auf 'SwitchToPagePart' basiert, und dass der Benutzer die Webseite angeben kann, die als nächste präsentiert werden soll, auch wenn diesem Handler nicht bekannt ist, welche Webseiten verfügbar sind:
handler TextFieldHandler type RUIHandler
   {initialUI = [instructions, Field1, myButton]}

   // Ein Stellvertreter
   switchFunction SwitchToPagePart;
   instructions TextLabel {text = "Type a page name and click the button."}; 
   Field1 Textfield{width = 200};
   myButton Button{text = "Go to the specified page", onClick ::= handleEvent};

   function handleEvent(e Event in)
      switchFunction(Field1.text);
   end
end
Zuletzt zeigt 'MainHandler' einfach den Text "Click to see your options." an, könnte jedoch auch eine Eingangsanzeige öffnen. Das folgende Beispiel zeigt den Code, einschließlich Logik, der Inhalte, die in anderen Handlern gespeichert sind, anzeigt:
handler MainHandler type RUIHandler{initialUI = [mainBox]}

   mainBox Box{columns = 1, children = [mainLabel]};
   mainLabel TextLabel{
      text = "Click to see your options.", 
      onClick::= mainEvent};
   buttonHandler ButtonHandler{switchFunction = switchTo};
   textFieldHandler TextFieldHandler{switchFunction = switchTo};
	
   function switchTo(target string in)
      case (strlib.upperCase(target))
         when ("TEXTFIELDHANDLER")
            mainBox.children = [textFieldHandler.instructions,
                                textFieldHandler.Field1, 
                                textFieldHandler.myButton];
         when ("BUTTONHANDLER")
            mainBox.children = [buttonHandler.button1, 
                                buttonHandler.button2, 
                                buttonHandler.button3];
         when ("MAINHANDLER")
            mainBox.children = [mainLabel];
      end
   end

   function mainEvent (e Event in)
      switchTo("ButtonHandler");
   end
end

Einbettenden Handler nach einem Serviceaufruf benachrichtigen

Der eingebettete Handler hat vielleicht überhaupt keine Widgets, ruft aber einen Service auf. Wie in Auf einen Service in Rich-UI zugreifen erläutert, ist ein Serviceaufruf in Rich-UI immer asynchron. Das bedeutet, dass der Anforderer, d. h. der Rich-UI-Handler, weiterhin ausgeführt wird, ohne auf eine Antwort vom Service zu warten. Der Benutzer kann seine Interaktion mit der Benutzerschnittstelle fortsetzen, während der Rich-UI-Handler auf eine Antwort des Service wartet. Nach dem Aufruf führt der Service eine Task aus und antwortet (in den meisten Fällen) dem Anforderer, indem er eine Funktion aufruft, die Sie im Rich-UI-Handler codieren. Diese Funktion wird als Rückruffunktion (Callback-Funktion) bezeichnet.

In der Rückruffunktion kann der eingebettete Handler den einbettenden Handler benachrichtigen. Betrachten Sie den folgenden EGL-Stellvertreterabschnitt, der eine Funktion definiert, die keine Parameter und keinen Rückgabewert hat:
delegate notifyPart() end
Das folgende Beispiel zeigt einen Entwurf eines eingebetteten Handlers:
handler MyModel type RUIHandler { onConstructionFunction = myFirstFunction }
   //Deklaration eines Stellvertreters
   notify notifyPart{};

   function myFirstFunction()
      call myService.myOperation(12) returning to myCallback;
   end
	
   function myCallback(returnValue STRING)
      notify();
   end	
end
Wie zuvor ordnet der einbettende Handler seine eigene Funktion dem Stellvertreter zu:
handler MyHandler type RUIHandler { onConstructionFunction = myFirstFunction }

   theModel MyModel;

   function myFirstFunction()
      theModel.notify = myNotification();
   end

   function myNotification()
      // Antworten, vielleicht durch Zugriff auf Details aus dem eingebetteten Handler
   end	
end

Feedback