Widget Communication Explained

3981
24
09-06-2011 11:45 AM
RobertScheitlin__GISP
MVP Emeritus
All,

  I have answered many threads where people are attempting to communicate between widget. So I thought that I would document in detail this previously undocumented portion of the Flex Viewer. In this PDF I explain what happens behind the scenes and provide code examples of what you need to add to your widgets. I also provide code for launching a widget from another widget so you can call a particular public function in the second widget. I hope this helps many.
Tags (2)
24 Replies
NitinBele
New Contributor
Thanks Robert, this is just awasome.
It really had a great insight on Widgets Communication.

Thanks again
Lu.
0 Kudos
FrankRoberts
Occasional Contributor III
Thanks Robert!    I appreciate the time you put into putting this document together for all of us.   It will be a great reference!

Frank
0 Kudos
FrankRoberts
Occasional Contributor III
Robert per the document I implemented the code as follows to open up a widget

var id:Number = ViewerContainer.getInstance().widgetManager.getWidgetId(incidentCreateWidget);
    var bWidget:IBaseWidget = ViewerContainer.getInstance().widgetManager.getWidget(id, true) as IBaseWidget;
    if (bWidget){
     var vSW:* = bWidget;
     vSW.queryFromURL("aaa",2,0);     
    }


In the above "incidentCreateWidget" is a string variable that is set from the xml for the widget.

It works great the first time the code is run (I'm running it from a button click event), however on the second time it throws the following error:

ReferenceError: Error #1069: Property queryFromURL not found on widgets.FrEditIncident.FrEditIncidentWidget and there is no default value.

Where "FrEditIncidentWidget" is the widget being called from the first one, where the code resides.



Any ideas?
Frank
0 Kudos
RobertScheitlin__GISP
MVP Emeritus
Frank,

   So does the FrEditIncidentWidget have a public function called queryFromURL?
0 Kudos
FrankRoberts
Occasional Contributor III
Ok, Got it,  your right it doesn't have that function, so of course it would fail.  So technically, if I just want to launch another widget, from widget "A" I just need this code:

var id:Number = ViewerContainer.getInstance().widgetManager.getWidgetId("Widget B");
var bWidget:IBaseWidget = ViewerContainer.getInstance().widgetManager.getWidget(id, true) as IBaseWidget;


Then if I want to pass values between the two I just need the following in Widget A:

var msArr:ArrayCollection = new ArrayCollection();
//Add an object or for example a string to the ArrayCollection
msArr.addItem("Text to pass to Widget B");    
addSharedData("MiniSearch_Search", msArr);



And then I can drop this code from Widget A, since I'm not calling a function:

if (bWidget){
var vSW:* = bWidget;
vSW.queryFromURL("aaa",2,0);
}


If I'm wrong feel free to set me straight.

Thanks yet again!
0 Kudos
RobertScheitlin__GISP
MVP Emeritus
Frank,

  All is good, but to clarify on the first code block if you are not going to call a public function on the widget than there is no need to get the base widget returned to you.

var id:Number = ViewerContainer.getInstance().widgetManager.getWidgetId("Widget B"); 
AppEvent.dispatch(AppEvent.WIDGET_RUN, id);


The above code is cleaner if you are not calling a function on the widget.
0 Kudos
JamesFaron
Occasional Contributor
Robert,

I am encountering a problem with getting the base widget returned. I have set up function triggered by a checkbox in the Print widget to include the Dynamic Legend. The Dynamic Legend opens as expected, but the code
 if(bWidget)
returns null when I debug, and of course anything after it does not happen. Here is the code I am using
private function incLegend():void
   {
    if(incLgnd.selected)
    {
     var id:Number = ViewerContainer.getInstance().widgetManager.getWidgetId("Dynamic Legend");
     var bWidget:IBaseWidget = ViewerContainer.getInstance().widgetManager.getWidget(id,true) as IBaseWidget;
     if(bWidget){
      var vSW:* = bWidget;
      vSW.exportImage();}


Is there something basic that I am missing?

Thanks,
Jim Faron
0 Kudos
RobertScheitlin__GISP
MVP Emeritus
Jim,

  The issue is that if the widget you are calling is not already loaded it takes some time to load and thus the bWidget is going to return null. One way to get around this is to use:

addSharedData("Legend_exportImage", null);
and implement the part of the document under figure 1.
0 Kudos
JamesFaron
Occasional Contributor
Robert,

Thanks for the advice, but I can't seem to get the necessary exchange of data to happen. I added:
private function incLegend():void
   {
    if(incLgnd.selected)
    {
     addSharedData("Legend_exportImage",null);
     var id:Number = ViewerContainer.getInstance().widgetManager.getWidgetId("Dynamic Legend");
     var bWidget:IBaseWidget = ViewerContainer.getInstance().widgetManager.getWidget(id,true) as IBaseWidget;

and then in the Dynamic Legend added:
private function sharedDataUpdated2(event:AppEvent):void
   {
    var dataTable:Hashtable = event.data as Hashtable;
    if(dataTable.containsKey("Legend_exportImage"))
    {
      exportImage();
    }
   }


When I debug, the dataTable key in the SharedDataUpdated2 is null. I fire the event listeners on init in the Dyanamic Legend.

Thanks,
Jim Faron
0 Kudos