Ok, modules in Flex are popular but I have no idea why documentation and examples on the different uses of Flex modules can be so scarce.
Anyway, for this question, I will take the classic Employee/Department example. I have a main.mxml that contains an mx:TabNavigator. Each tab is loaded by an s:ModuleLoader.
Tables: Employees {empID,empName,deptID}, Deparments {deptID,deptName}
The Tab Navigator contains only one tab (for our example) called Employee. I have an Employee.mxml module. In that module, I have a datagrid that is populated with Employee details. I use the getEmployees($deptID) function. This function, as you may guess, returns me an array of Employees who work in a particular department.
Outside the TabNavigator, I have a departmentDropDownList that is populated with departments.deptName.
My objective is to load the Employee module when I select a particular department from the DropDownList. I have a changeHandler for the DropDownList that can give me the deptID.
protected function departmentDropDownList_changeHandler(event:IndexChangeEvent):void
{
MyDeptID=departmentDropDownList.selectedItem.deptID;
//var ichild:*=employeeModule.child as IModuleInfo;
}
Now, the million dollar question is: How do I pass this deptID to the Employees module. The latter has an employee_creationCompleteHandler that calls getEmployees(deptID):
protected function EmployeesDg_creationCompleteHandler(event:FlexEvent):void
// I only need to get the deptID from the departmentDropDownList outside the Employee module.
// If I could create a global variable deptID, that would be great!
getEmployeessResult.token=employeeService.getEmployeess(deptID);
}
I have attempted to use [Bindable] variables but without success.
I would appreciate your suggestions.
You can't really guarantee that the deptID will be set when creationComplete runs--it sounds like you're waiting for a server result--so this is probably not the best way to handle it.
One of the things you need to be careful of is directly referencing the full Module Class from the main Application, because the point of modules is that you should not compile in the module Class into the main Class (to reduce file size/load times).
So what you might want to do is create an Interface. This creates a "contract" between the main application and the Module without carrying all the implementation code with it. That might look something like this
public interface IEmployeeModule {
function set deptID(value:int):void;
}
Then, your Module might have code that's something like this:
protected var _deptID:int;
public function set deptID(value:int):void {
_deptID = value;
var token:AsyncToken=employeeService.getEmployeess(deptID);
token.deptID = value;//in case department id changes, you can determine if you still care
}
Note that, though global variables seem like a wondermous idea when your project is small, they are a very bad habit to get into. It can be almost impossible to repair a project that starts out with these and then grows to the point that no one can figure out exactly which of the hundreds or thousands of Classes that have access to a variable are changing it in the wrong way at the wrong time.
You ESPECIALLY don't want to use global variables with Modules, as they can cause really bad problems when the modules start fighting over the definition.
We solved this problem with the use of Cairngorm v2. Think of it as a message bus for ActionScript, one of several. In your departmentDropDownList_changeHandler method we would create a DeptChanged event with the ID as the payload, and send it on the bus to any and all subscribers to that message type. It worked pretty well for us, and made things more event driven, which in some circles is considered a good thing in itself.
@J_A_X I haven't had good luck with using Robotlegs out of the box with Modules. It seems that something goes wonky with the security contexts, even though it shouldn't. I had to use Joel Hooks' ModuleContext to make it work right, even though my needs were fairly basic.