Drink and enjoy mojito

Give me more mojits

How to include more than one mojit in your page

Introduction

You know how to do an hello world with mojito? Congratulations!

Can you say hello to Mars, the Underworld and the Middle Earth at the same time?

Yes, you can do that by using composite mojits.

A composite mojit is a mojit that has children, and render them inside its own view, by using the ActionContext Composite Addon

One parent and his grand-parent

In order to have a complete HTML skeleton, we use the HTMLFrameMojit. This mojit can have only one direct child. This child will be a custom mojit Body that will get many children. In our example those children will be differents instances of a same mojit. We will use the configuration object to make them change a little bit.

Code

First step

We first create the mojito application. If you do not have mojito installed yet, it is a good time to use npm.


      npm -g install mojito
      mojito create app HelloMultiverse
      

You can install mojito locally, it will allow you to run your app à la node.


      mojito start
      node server.js
      

Config

In application.json we declare our three different mojits (the grand-parent, the parent and children). The children all have the same type and only differs by there name and additional configuration. Every children will say hello from differents places.

application.json can look scary, be careful to have a valid json. Do not copy paste this one (comments are not valid JSON). You could also use YAML.


[{
  "settings": [ "master" ],
    "appPort": "8666",
    "specs": {
      "multiMojitFrame": { //The name of the mojit. In template we reference to it, not the type
        "type": "HTMLFrameMojit", //The grand-parent can only have one child.
        "config": {
          "title": "Hello from many places",
          "assets": {
            "top": {
              "css":[ //we include some css files at the top of the produced html file. This is a feature of the HTMLFrameMojit
                "http://yui.yahooapis.com/combo?3.9.1/build/cssnormalize/cssnormalize-min.css&3.9.1/build/cssgrids-responsive/cssgrids-responsive-min.css&3.9.1/build/cssbutton/cssbutton-min.css&gallery-2013.03.27-22-06/build/gallerycss-csslist/gallerycss-csslist-min.css&gallery-2013.03.27-22-06/build/gallerycss-csstable/gallerycss-csstable-min.css&gallery-2013.03.27-22-06/build/gallerycss-cssform/gallerycss-cssform-min.css",
              "https://rawgithub.com/tilomitra/prettypages/gh-pages/ui.css",
              "https://rawgithub.com/ccampbell/rainbow/master/themes/github.css",
              "/static/body/assets/ui.css"
                ]
            }
          },
          "child": {
            "type": "body", //The parent. He will contain many children.
            "config": {
              "children": {
                "world": { //again, this is the name. We will see it as {{{world}}} in the mustache template.
                  "type": "helloMojit", //world is a helloMojit mojit, like his siblings.
                  "config":{ //we can pass some config. parameters. Useful.
                    "helloClass": "world",
                    "what": "world"
                  }
                },
                "mars":{
                  "type": "helloMojit", //Another helloMojit mojit.
                  "config":{
                    "helloClass": "mars",
                    "what": "mars"
                  }
                },
                "underWorld":{
                  "type": "helloMojit",
                  "config":{
                    "helloClass": "underworld",// Dracula may be there.
                    "what": "underworld"
                  }
                },
                "middleEarth":{
                  "type": "helloMojit",
                  "config":{
                    "helloClass": "middleearth",// Gandalf will be there
                    "what": "middleearth"
                  }
                }
              }
            }
          }
        }
      }
    }
},
{
  "settings": [ "environment:development" ],
  "staticHandling": {
    "forceUpdate": true
  }
}]

It is necessary to setup a route. We will tell that our root path "/" goes to the "HTMLFrameMojit.index" action. It is a quite common setup for simple app (but you may setup more routes thant this one).

Again, be careful with the syntax.


[{
  "settings": [ "master" ],
    "multiMojitFrame": {
      "path": "/",
      "verb": ["GET"],
      "call": "multiMojitFrame.index" //The index method of the multiMojitFrame (an HTMLFrameMojit)  controller will be called.
    }
}]

Ingredients

HTMLFrameMojit being kindly offered by our Y! friends (yahoo open bar!), we only need to create the body mojit and the helloMojit mojit.


      mojito create mojit body
      mojito create mojit helloMojit
      

Body: the composite parent

We will change the default controller and view, and drop the model.

The controller needs to use the mojito-composite-addon in order to execute and render its children. That's all.

We include the mojito-composite-addon by including it in the 'requires' array. Then instead of useing "ac.done" we call "ac.composite.done".


YUI.add('body', function(Y, NAME) {

    Y.namespace('mojito.controllers')[NAME] = {
        index: function(ac) {
                ac.composite.done();
        }

    };

}, '0.0.1', {requires: ['mojito', 'mojito-composite-addon']});
    

The view will be the chrome of our app, the markup that surrounds or childrend mojits. If you want to give your page a general structure (grid) that is not mojit specific, you will do it here.

In the mustache template, you will include the mojits by putting their name (as defined in application.json) between triple curly braces.

The following shows a centered responsive yui3 grid (2X2), containing 4 mojits.

{{{world}}}
{{{mars}}}
{{{middleEarth}}}
{{{underWorld}}}

Hello children

The child mojit is super simple. No model, simple view. It's doing one interesting thing: read its own config. Remember you can load addons by adding them in the 'requires' array property of the last argument of YUI.add.



YUI.add('helloMojit', function(Y, NAME) {

    Y.namespace('mojito.controllers')[NAME] = {
            index: function(ac) {
                //access mojit config thanks to the 'mojito-config-addon'
                var helloClass = ac.config.get('helloClass') || 'defaultHello',
                  what = ac.config.get('what') || 'world!';
                //we add a css. it will be inserted in the HTMLFrameMojit
                ac.assets.addCss('./index.css');
                ac.done({ //the data we pass to the view
                  "helloClass": helloClass,
                  "what": what
                });
        }
    };
//'requires' is an array of modules/addons we need in the controller.
}, '0.0.1', {requires: ['mojito', 'mojito-assets-addon', 'mojito-config-addon']});
      

The view is pretty simple too, the class and the text will change with the data given by the controller. Again, the whole mojit is wrapped in a div with a special id.

 
Hello {{what}}

Start it, browse it, et voilà!

Warnings

The 'ac.composite.done' method executes the action specified in the 'action' property of child config, or , if none, the 'index' action. But not the current command action. You need to be aware of that when setting up your routes.

Links