Reputation: 2169
What I want to achieve is very simple, I want to have a main menu all across my application, with the same functionality for all the views.
I would like to create a view that contains exclusively the menu portion plus its own viewcontroller. What would be the [best] way to achieve this?
I am using ExtJS 5 implementing the MVVM paradigm.
Thanks!
Upvotes: 1
Views: 1518
Reputation: 25001
I would create a main view, in which you define the fixed parts of the application, as well as a container with layout 'fit' to hold the changing "views". Instead of layout 'fit', this could also be a tab panel or something. Nothing prevents you from add behaviour to the fixed part of this main view using a view controller for it of course.
Pretty straightforward in fact. Then, you'll change the current app view by putting it into the main view's central container. You'll need some kind of decision logic and configuration data to define the available views in your application. This would probably best to wrap that in a single place dedicated to this very task only, that is an app controller (rather than the view controller).
Here's an example fiddle, and bellow is the reasoning explaining the different parts of the code:
So, you'd start with a view like that:
Ext.define('My.view.Main', {
extend: 'Ext.container.Container',
xtype: 'main', // you can do that in ext5 (like in touch)
// shortcut for that:
//alias: 'widget.main',
controller: 'main',
layout: 'border',
items: [{
xtype: 'panel',
region: 'west',
layout: {type: 'vbox', align: 'stretch', padding: 5},
defaults: {
margin: 5
},
items: [{
xtype: 'button',
text: "Say Hello",
handler: 'sayHello'
}]
},{
// target for app's current view (that may change)
xtype: 'container',
region: 'center',
layout: 'fit'
}]
});
Ext.define('My.view.MainController', {
extend: 'Ext.app.ViewController',
alias: 'controller.main',
sayHello: function() {
Ext.Msg.alert("Controller says:", "Hello :-)");
}
});
Then, you set this main view as the "viewport" of your application. I also add a method to change the center view. I think the Application instance is a good place for that, but you could move this method to another dedicated app controller...
Ext.application({
name : 'My', // app namespace
// in real life, Main view class would lie in another file,
// so you need to require it
views: ['Main'],
// from ext 5.1, this is the config to auto create main view
mainView: 'My.view.Main',
// we also register a ref for easy retrieval of the main view
// (the value 'main' is the xtype of the main view -- this is
// a component query)
refs: {
main: 'main'
},
setCenterRegion: function(cmp) {
// getter generated by refs config
// you could another layout in the main view, and another component query of course
var center = this.getMain().down('[region=center]');
// replace the current center component with the one provided
center.removeAll();
center.add(cmp);
}
});
So, now, you can change the view with code like this:
My.getApplication().setCenterRegion(myView);
You could wire it through the ViewController of the main view, and using it as handlers in your view. For example, in your ViewController:
changeView: function() {
// retrieve the next view, this is application specific obviously
var myView = ...
// My.getApplication() gives you the instance created by
// Ext.getApplication in namespace 'My'
My.getApplication().setCenterRegion(myView);
}
And, in your main view, use an item like this:
{
xtype: 'button',
text: "Change view (by view controller)",
handler: 'changeView'
}
That could be fine for simple applications, nevertheless that seems like mixing of concern. Deciding about application level view swapping seems more like an application controller's business. So, I would rather recommend to put the changeView
method in an app controller, and exposes it to components with a component query, like this:
Ext.define('My.controller.Main', {
extend: 'Ext.app.Controller',
config: {
control: {
// components will have to match this component query
// to be animated with the change view behaviour
'#changeView': {
click: 'changeView'
}
}
},
changeView: function() {
My.getApplication().setCenterRegion(/*
...
*/);
}
});
And you would hook the behaviour to components in any view like this:
{
xtype: 'button',
text: "Change view (by app controller)",
// will be matched by the controller component query
itemId: 'changeView'
}
Upvotes: 2
Reputation: 5856
This is a pretty broad question about how to architect the app that is pretty difficult to answer without knowing more about other parts of the app.
Generally, anything application global (that is not the application container/viewport) is probably easiest to implement with MVC. Menu controller (MVC controller) would listen to menu events and then it would drill down the component hierarchy to call components' API methods to execute the actions.
I could be more specific if I knew the app.
Upvotes: 3