Getting back to JavascriptMVC

Having decided on a basic navigation tool, I needed to get it from demo-land to actual implementation.

First thing, I had to decide a million things about the actual structure and this is hard for me. I have three full levels of control. The topmost basically comes down to a set of departments, each having a set of functional roles that each require some set of tools. Last time I was using an MVC framework, the navigation was separate from the mvc setup. This didn't seem right so I made a navigation controller. This, of course, means that I have to figure out inter-controller communications. I also have to figure out an addressing structure.

Remember, this is javascript. There are no real URLs. There is exactly one html file and any url goes to it. What I want to do is make it so that URLs look normal and are meaningful. If I can't find a way to update the URL in the menu bar, I will go for a specific bookmark user interface widget where the user will be able to copy a link that will work. JavascriptMVC has some function that purports to do this. It looks like it relies on the URL anchor (#). I'll change that if I can. I want perfectly clean URLs.

It wasn't too hard (ha!). I made a class for navigation elements, set a click listener for them. I use the id of the control to tell me the 'path' which I will use as if it came from the original page entry using a bookmarked URL.

The URL is structured as http://domain.com/Department/Role/Tool/arg1/arg2. And here I find another issue. The usual MVC URL structure is http://domain.com/Controller/Action/args. That suggests that the Department field would correspond to the controller.
Eventually, I decided to count from the other end. Considering the last two to be the Controller/Action and that makes more sense to me. So, I name the controllers, "DeptnameRolenameController" and it will have, among other things, some methods called "Toolname". The real use for the department is to name a DIV that will serve as a canvas for it's controllers and to change the toolbar that is displayed.

My current problem is that I can't figure out how to communicate to my controllers. The current structure is that the navigation controller receives a navigation click. It figures out what controller and action needs activation. Presently, I issue a 'navigationClick' event. All of my appropriate controllers listen for it, check the path that is sent with it and do what comes naturally, ie, ignore it or act on it. This has the advantage that I can have non-navigation things pay attention to the event, logging comes to mind.

The downside is that I've had some trouble making sure that all events get processed in the right order when there are several listeners. It also seems a little wasteful to have all controllers listening. I'd like to be able to simply address the controller.action() but I can't.

I fully believe that I am missing something fundamental but have not been able to figure it out. I have tried everything I can think of. Fortunately, publish/subscribe works.

2 responses
Hi There! just wondering if you ever found a "good" way to communicate between your controllers. i find myself in the same boat at the moment.

-Shane

Yes, I have settled on a communication pattern based on callbacks.

When I instantiate a controller, I pass it a callback, eg,

$('#xx).subordinateControllerName({
parameters:{},
creatorAccess:this.callback('subordinateControllerReceiverMethod')
});

The callback has as standard structure for communication.

subordinateControllerReceiverMethod:function(control, parameter){
switch(control){
case 'whatever':
this.whatever(parameter);
break;
case 'setAccessFunction':
this.subControlAccessFunction=parameter;
break;
}
}

The subordinate controller can use this function to say whatever needs to be said to its creator.

In the subordinateController,

init:function(element, parameters){
this.creatorAccessFunction=parameters.creatorAccess;
//this part is key:
this.creatorAccessFunction('setAccessFunction', this.callback('creatorReceiverFunction'));

},

creatorReceiverFunction:function(control, parameter){
switch(control){
case 'changeState':
this.changeState(parameter);
break;

}

}

See what's happening?

When the subordinate controller starts up, it sends a callback function to the creator. Then, each of them has a direct channel to the other.

My best example is a button widget I wrote. I need its creator to be able to do things like make it active or inactive. The button needs to be able to tell the creator it was clicked.

The creator has statements like:

this.saveButton.accessFunction('setInactive)');

The button has:

this.creator.accessFunction('clicked');

Another thing I have generates an outline for selecting things. It might say,

this.creator.accessFunction('setSelection', selectedIdNumber);

I've now used this pattern a hundred times and continue to be very happy with it. Sometimes the list of cases in the switch statements is very complicated. Other times it's trivial. It always has the 'setAccessFunction' case, of course.

It's turned out to be so useful, that I automatically include it in pretty much all subordinate controllers. It is rare that I don't eventually find a reason for my controllers to talk to each other.