EnyoJS 2.7 Tutorial : Navigation System

Today, we going to cover a little on how views pages are linked up and making simple page navigation.

FirstPage has a button that will load up SecondPage and;
SecondPage has a back button that will load up FirstPage.

Let’s get started, modify index.js to load up FirstPage. Download this source file to follow the tutorial, copy content into “simplenav” folder (you may change it to different folder by changing the reference in package.json under name file).

Download Here


index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var ready = require('enyo/ready');
var kind = require('enyo/kind');
var control = require('enyo/Control');
var FirstPage = require('./src/viewpages/FirstPage');
 
var App = control.kind({
	classes: 'enyo-fit',
	components: [
		{ kind: FirstPage }
]});
 
ready(function() {
	new App().renderInto(document.body);
});

FirstPage.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
var kind = require('enyo/kind');
var Button = require('enyo/button');
var FittableRows = require('layout/FittableRows');
var SecondPage = require('../viewpages/SecondPage');
 
module.exports = kind({
    name: 'FirstPage',
    data: null,
    kind: FittableRows,
    classes: 'enyo-fit',
    components:[
        {
                fit:true,
                classes:"centerize",
                components:[
                    {
                        tag:"h1",
                        content:'This is the First Page'
                    }
                ]
        },
        {
            kind:Button,
            ontap:"handle_Goto2ndPage",
            content:"Goto 2nd Page"
        }
   ],
   create: function(){
       this.inherited(arguments);
   },
   rendered : function(){
       this.inherited(arguments);
 
   },
   handle_Goto2ndPage: function(inSender,inEvent){
        console.log("Goto 2nd Page");
        // Typically we just initialized SecondPage kind and render into document.body.
        // If the project has very simple one way page A to B to C navigation this should just work fine.
        new SecondPage().renderInto(document.body);
   }
});

SecondPage.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
var kind = require('enyo/kind');
var Button = require('enyo/button');
var FittableRows = require('layout/FittableRows');
//var FirstPage = require('../viewpages/FirstPage');
 
module.exports = kind({
    name: 'SecondPage',
    data: null,
    kind: FittableRows,
    classes: 'enyo-fit',
    components:[
        {
                fit:true,
                classes:"centerize",
                components:[
                    {
                        tag:"h1",
                        content:'This is the Second Page'
                    }
                ]
        },
        {
            kind:Button,
            ontap:"handle_Goto1stPage",
            content:"GoBack 1st Page"
        }
   ],
   create: function(){
           this.inherited(arguments);
   },
   rendered : function(){
           this.inherited(arguments);
   },
   handle_Goto1stPage:function(inSender,inEvent){
            console.log("TODO: Goto 1st Page");
            //new FirstPage().renderInto(document.body);
   }
});

Notice, in SecondPage.js I’ve already commented the FirstPage reference in line 4 and 36. If you un-comment it and compile. You will encounter a reference error. One of the main problem of View Page kind in 2.7 is that, you cannot require the same View Page more than once (be it in other view pages).

My Solution

Based on diagram above, what we need is the first page to load all the pages (except PreLoader.js itself) references into a NavigationService kind that stores references of each pages in statics. Each Viewpages will then, include only NavigationService and call GotoPage(matching string parameter) method to change to target page.

Download the next source code to follow up.

Download Here


Key difference in this solution code is the PreLoaderPage and NavigationService. I placed NavigationService.js into modules folder, a kind that doesn’t have any UI or controls. I place all my utils, wrappers and helpers here – but that’s just my classification. index.js now points to PreLoaderPage.js as the first page.

PreLoaderPage.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var kind = require('enyo/kind');
var Button = require('enyo/button');
var FittableRows = require('layout/FittableRows');
var NavigationService = require('../modules/NavigationService');
 
 
var FirstPage = require('../viewpages/FirstPage');
var SecondPage = require('../viewpages/SecondPage');
 
module.exports = kind({
    name: 'PreLoaderPage',
    routes: {
        "FirstPage": new FirstPage(),
        "SecondPage": new SecondPage()
    },
    kind: FittableRows,
    classes: 'enyo-fit',
    components:[
        {
          content:'Loading...'
        }
   ],
   create: function(){
           this.inherited(arguments);
           NavigationService.Init(this.routes);
   },
   rendered : function(){
           this.inherited(arguments);
           // Once everything is rendered and loaded. Move to FirstPage();
           // GotoPage will match string into the required reference of the page
           // and render it into body.
           NavigationService.GotoPage("FirstPage");
   }
});

NavigationService.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var kind = require('enyo/kind');
var Component = require('enyo/Component');
module.exports = kind( {
    name: 'NavigationService',
    statics:{
        Routes:null,
        Index:0,
        NavigationStack:[],
        Init:function( routes ){
            this.Routes = routes;
        },
        PushPage: function( pageName ){
            this.NavigationStack.push(this.Routes[pageName]);
            this.Index = this.NavigationStack.length-1;
            this.NavigationStack[this.Index].renderInto(document.body);
        },
        PopPage: function(){
            this.NavigationStack.pop();
            this.Index = this.NavigationStack.length-1;
            this.NavigationStack[this.Index].renderInto(document.body);
        },
        GotoPage: function( pageName ){
            // Manually travel into the page without updating Navigation Stack
            this.Routes[pageName].renderInto(document.body);
        }
 
    }
});

All we need now is to reference NavigationService and use it’s method in every viewPage. For example FirstPage.js…

FirstPage.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
var kind = require('enyo/kind');
var Button = require('enyo/button');
var FittableRows = require('layout/FittableRows');
var NavigationService = require('../modules/NavigationService');
 
module.exports = kind({
    name: 'FirstPage',
    data: null,
    kind: FittableRows,
    classes: 'enyo-fit',
    components:[
        {
                fit:true,
                classes:"centerize",
                components:[
                    {
                        tag:"h1",
                        content:'This is the First Page'
                    }
                ]
        },
        {
            kind:Button,
            ontap:"handle_Goto2ndPage",
            content:"Goto 2nd Page"
        }
   ],
   create: function(){
       this.inherited(arguments);
   },
   rendered : function(){
       this.inherited(arguments);
 
   },
   handle_Goto2ndPage: function(inSender,inEvent){
        //Summon the great NavigationService and Set Sail!
        NavigationService.GotoPage("SecondPage");
   }
});

Phew that covers today’s tutorial. Hopefully this helps 😉

Comments

comments