I've written before about how difficult I've found it to figure out how to use Modules for eLearning style structures within Flex. It seems to me I may have hit upon an approach that works. The new documentation on Modules has an example that shows creating an Interface so that you have a known "contract" between the Module and the parent container. The example shows how to pass information into the Module, but didn't seem at all concerned about passing information back out. So I put my thinking cap on, and went to researching.
The first thing that seemed obvious to me was that you'd need to have some sort of event that would be propogated from the Module to tell the parent container that something had happened. So, I went and looked at the documentation about how to handle events. And I really, really tried to figure out a way to do it just with the implementation of the functions from the Interface. But functions in an Interface are kinda tricky. They're fairly plain Jane (in the Interface itself they're just stubs, with no implementation) and are really designed to be called from whatever is Interfacing with the Interfacee (as it were). I couldn't figure out a way to use them to push information out with them.
Instead, what I did was create a function that will return the name of the event that the Module expects to send out to the container. This allows the container to attach an event listener for that event without having to know up front what it will be called. So, for instance you could have an ElearningEvent.MENU_CLICK or an ElearningEvent.MC_SELECTION.
Where did the names for these events come from? Well, let me back up. I wrote a custom event class called ElearningEvent, specifically for handling events from my own eLearning Modules. I imported this class both into the Module file and into the Container file. It had public static constants in it that defined the ELearningEvent types. Ultimately, I plan to extend it so that more custom events can convey more information, such as whether a question was right or wrong (right now, it just publishes a value and ID).
So now that I've rambled all over the map, let me distill the process into a nutshell:
- First, I wrote the Interface .as file (IELearning.as), which essentially said "these are the functions you can use to access me, and here are the arguments I expect and what I will return."
- Next, I wrote the ELearningEvent class, which defined my custom event, including constants covering the event types included in it. I made it Inspectable so that Flex Builder would help with the typing.
- I added the implements element to the Module to specify that it implemented IELearning. I added the implementation of the Interface functions, including the one that published the specific event for this Module (in this case, a MENU_CLICK). And I added logic to listen for a click on the menu and generate my ElearningEvent.
- In the containing Application, I added logic similar to the logic in the Module docs to retrieve a reference to the Module child when it loaded. The difference is, I also asked for the name of the event that the Module child was planning to generate, and attached an event listener to the child.
The Module file was already inserted into the Application file, and I'd already worked out its base functionality before I started the process above.
I'm still not sure why an Interface is the suggested solution for this. I would think that maybe just writing an ordinary class, might be better, or even a fake abstract class.