Marionette.Toolkit.App
is an extension of Marionette.Application
. Its purpose is to provide an object with a initialize
/start
/stop
/destroy
lifecycle. App
has several mixins:
StateMixin
to maintain application state.EventListenersMixin
to bind all events to anApp
while running (and only those) will be remove when stopped.ChildAppsMixin
to manage the addition and removal of childApp
s and relating the childApp
lifecycle with the parentApp
lifecycle.ViewEventsMixin
for proxying events from the app's view to the app.
- Using Toolkit App
- Lifecycle Settings
- Lifecycle API
- Lifecycle Events
- Application State
- Application Region
- Application View
Beyond the Toolkit App's lifecycle, its biggest feature is childApps.
This allows children to be tied to the lifecycle of their parent's lifecycle.
As Toolkit App extends Marionette.Application
it can be used as a drop-in replacement.
Call start
immediately after initialize
if true
. Default value is false
.
Can be added as an option when instantiated or defined on the App
definition.
It can also be defined as a function returning a boolean value.
const MyApp = App.extend({
initialize(){
this.isRunning() === false;
},
startAfterInitialized: true
});
const myApp = new MyApp();
myApp.isRunning() === true;
If set true
this App
will not be destroyed when its parent App
is destroyed.
Default value is false
.
Can be added as an option when instantiated or defined on the App
definition.
It can also be defined as a function returning a boolean value.
const myApp = new App();
const myChildApp = myApp.addChildApp('myChildApp', {
AppClass: Marionette.Toolkit.App,
preventDestroy: false
});
const myPreventDestroyApp = myApp.addChildApp('myPreventDestroyApp', {
AppClass: App,
preventDestroy: true
});
myApp.destroy();
// logs true
console.log(myChildApp.isDestroyed());
// logs false
console.log(myPreventDestroyApp.isDestroyed());
If set true
this App
will start when its parent App
starts.
Default value is false
.
Can be added as an option when instantiated or defined on the App
definition.
It can also be defined as a function returning a boolean value.
const myApp = new App();
const myChildApp = myApp.addChildApp('myChildApp', {
AppClass: App,
startWithParent: false
});
const myStartWithParentApp = myApp.addChildApp('myStartWithParentApp', {
AppClass: App,
startWithParent: true
});
myApp.start();
// logs false
console.log(myChildApp.isRunning());
// logs true
console.log(myStartWithParentApp.isRunning());
Default value is null
.
It can also be defined as a function returning a boolean value.
If restartWithParent
is true
the child app will stop and start with the parent when restart
ing.
If restartWithParent
is false
the child app will neither stop nor start with the parent when restart
ing.
If restartWithParent
is null
the child app will respect startWithParent
and stopWithParent
when restart
ing.
const myApp = new App();
const persistantChildApp = myApp.addChildApp('persistantChildApp', {
AppClass: App,
restartWithParent: false
});
persistantChildApp.on('stop start', function(options) {
console.log(this.isRestarting());
});
// does not log
myApp.restart();
const restartingChildApp = myApp.addChildApp('restartingChildApp', {
AppClass: App,
restartWithParent: true
});
myApp.start();
restartingChildApp.on('stop start', function(options) {
console.log(this.isRestarting());
});
// logs true twice
myApp.restart();
If set true
this App
will stop when its parent App
stops.
Default value is true
.
Can be added as an option when instantiated or defined on the App
definition.
It can also be defined as a function returning a boolean value.
const myApp = new App();
const myChildApp = myApp.addChildApp('myChildApp', {
AppClass: App,
stopWithParent: false
});
const myStopWithParentApp = myApp.addChildApp('myStopWithParentApp', {
AppClass: App,
stopWithParent: true
});
myApp.start();
myChildApp.start();
myStopWithParentApp.start();
myApp.stop();
// logs true
console.log(myChildApp.isRunning());
// logs false
console.log(myStopWithParentApp.isRunning());
This method sets the App
to its running state.
Events added after start
are registered for removal onStop
.
This triggers "before:start" / "start" events.
Initial state can be passed as an option to start
.
const myApp = new App();
myApp.on('start', function(options){
console.log('My App Started!');
options.foo === true;
this.getState('bar') === 'baz';
});
// false
myApp.isRunning();
const initialState = {
bar: 'baz'
};
// "My App Started!" logged
myApp.start({
foo: true,
state: initialState
});
// true
myApp.isRunning();
// Nothing is logged
myApp.start();
This method saves the current state of the app before stopping it. It then starts the app again with the preserved state attributes. If an options object parameter is provided, that will also be preserved alongside the state attributes.
const myApp = new App();
myApp.on('before:start', function(data) {
console.log(data);
});
const initialState = {
foo: 'bar'
};
// logs { state: { foo: 'bar' } }
myApp.start({
state: initialState
});
myApp.setState('foo', 'baz');
const options = {
foo: 'bar'
};
// logs { state: { foo: 'baz' }, options: { foo: 'bar' } }
myApp.restart(options);
This method stops the App
's running state.
Events added after start
are registered for removal onStop
.
This triggers "before:stop" / "stop" events.
const myApp = new App();
myApp.on('stop', function(options){
console.log('My App Stopped!');
options.foo === true;
});
// Nothing is logged
myApp.stop();
myApp.start();
// true
myApp.isRunning();
// "My App Stopped!" logged
myApp.stop({
foo: true
});
// false
myApp.isRunning();
// Nothing is logged
myApp.stop();
Returns a Boolean indicating whether or not the App
is running.
const myApp = new App();
myApp.start();
myApp.isRunning() === true;
myApp.stop();
myApp.isRunning() === false;
Returns a Boolean indicating whether or not the App
is restarting.
const myApp = new App();
myApp.on('before:stop', function(options) {
console.log(this.isRestarting());
});
myApp.start();
// logs true
myApp.restart();
// logs false
myApp.stop();
This method stops the App
if running and sets the App
's state to destroyed.
const myApp = new App();
myApp.start();
myApp.isRunning() === true;
myApp.isDestroyed() === false;
myApp.destroy();
myApp.isRunning() === false;
myApp.isDestroyed() === true;
The "before:start" event and corresponding onBeforeStart
method are triggered just before the App
isRunning
is set true
. This is the appropriate place to set up your app's initial state. Calling setState
in onBeforeStart
will not trigger any events.
The "start" event and corresponding onStart
method are triggered after the App
isRunning
is set true
. Once onStart
is run, state event listeners have been applied.
const MyApp = App.extend({
// ...
onBeforeStart(options){
// ...
},
onStart(options){
// ...
}
});
const myApp = new MyApp({...});
myApp.on('before:start', function(options){
// ...
});
myApp.on('start', function(options){
// ...
});
The "before:stop" event and corresponding onBeforeStop
method are triggered just before the App
isRunning
is set false
.
The "stop" event and corresponding onStop
method are triggered after the App
isRunning
is set false
.
const MyApp = App.extend({
// ...
onBeforeStop(options){
// ...
},
onStop(options){
// ...
}
});
const myApp = new MyApp({...});
myApp.on('before:stop', function(options){
// ...
});
myApp.on('stop', function(options){
// ...
});
A StateModel
class can be passed to App instantiation as an option or defined on the App.
const myApp = new MyApp({
StateModel: MyStateModel
});
A stateEvents
hash can be passed to App instantiation as an option or defined on the App.
const MyApp = App.extend({
stateEvents: {
'change': 'onChangeState'
}
onChangeState() {
// Handle state change event
}
});
Application state can be passed to App start
as a state
option. The state is maintained while the app is running.
myApp.start({
state: {
limit: 10
}
});
myApp.getState('limit') === 10;
A Marionette.Region
instance can be passed to App start
as a region
option,
setting the App region, making it available to both before:start
and start
events.
myApp.start({
region: myRegion
});
myApp.getRegion() === myRegion;
Calling setRegion
will replace the App
's region making it available to the App's Region API.
Unlike Marionette.Appliation
's region attribute, setRegion
only accepts a Region instance.
myApp.setRegion(myView.getRegion('appRegion'));
getRegion
performs two functions. When passed no arguments returns the app's region.
You can also give getRegion
a region name string which will attempt to return a region from the app's view.
It is sugar for myApp.getView().getRegion('regionName') === myApp.getRegion('regionName');
.
const MyApp = Toolkit.App.extend({
region: '#app-hook'
});
const myView = new Mn.View({
template: MyTemplate,
regions: {
foo: '#foo'
}
});
myApp.getRegion(); // #app-hook region
myApp.showView(myView);
myApp.getRegion('foo'); // foo region on myView
A Marionette.Application
can have an associated view shown in its region with showView
.
Toolkit takes this a step further and proxies that view's showChildView
and getChildView
. This is simply sugar for common patterns.
A View instance can be passed to App start
as an option,
setting the App view, making it available to both before:start
and start
events.
myApp.start({
view: myView
});
myApp.getView() === myView;
Assign a view to an App. There are two notable use cases for this.
First, this allows you to use App.getRegion('regionName')
or App.showChildView
without first showing the view in the App's region. This way all of the App's children
can be setup and rendered prior to attaching anything to the DOM.
const MyApp = Toolkit.App.extend({
onStart() {
this.setView(myLayoutView);
this.startChildApp('child', { region: this.getRegion('child') });
this.showChildView('title', 'My App');
this.showView();
}
});
The second is when you want to associate an App with a view already in a region or one that won't be shown in a region.
const myView = new Mn.View.extend({
el: $('#existing-dom'),
regions: {
foo: '#foo'
}
});
const myApp = new MyApp();
myApp.start();
myApp.setView(myView);
myApp.getRegion('foo') === myView.getRegion('foo');
setView
returns the view.
const myView = myApp.setView(new MyView());
// myApp.listenTo(myView, ...);
Returns the view instance associated with the App.
myApp.setView(fooView);
myApp.getView() === fooView;
myApp.showView(barView);
myApp.getView() === barView;
myApp.getRegion().show(bazView);
myApp.getView() === bazView;
Shows a view instance in the App's region.
The first argument for showView
is the view instance, but if left undefined the App will
attempt to use the current view ie: myApp.getView()
. The second argument is region.show options
myApp.showView(myView, { replaceElement: true });
// Alternatively
myApp.setView(fooView);
// Show fooView
myApp.showView();
showView
returns the view.
const myView = myApp.showView(new MyView());
// myApp.listenTo(myView, ...);
This method will help when a region from the App's view is needed.
It has the same API as a Marionette.View
's showChildView
and returns the show view.
myApp.showChildView('fooRegion', myChildView, 'fooArg');
//is equivalent to
myApp.getView().getRegion('fooRegion').show(myChildView, 'fooArg');
showChildView
returns the child view.
const myView = myApp.showChildView('fooRegion', new MyView());
// myApp.listenTo(myView, ...);
Like showChildView
, getChildView
is a helper for getting a view shown in a region belonging to the App's view.
It has the same API as a Marionette.View
's getChildView
.
myApp.getChildView('fooRegion');
//is equivalent to
myApp.getView().getRegion('fooRegion').currentView;
View events for an App's view can be proxied following a very similar API to what you would
expect on a Marionette.View
and Marionette.CollectionView
with their children.
You can use viewEvents
, viewTriggers
and viewEventPrefix
for auto-proxying events.
For more information see the ViewEventsMixin documentation.