Welcome to nooljs (Beta)

Full stack JavaScript framework built using famous open sources libraries Nodejs, Angularjs, expressjs, and socket-io.

Quick Start

  1. Install nooljs with npm

    $ npm install nooljs -g

  2. Create new nooljs project by running command
          $ nooljs
        

    It will ask project name. enter the project name( example testprj). It will create new folder for the project and sample application.

  3. Go the new project folder
    $ cd testproj 
  4. Update the npm dependency packages
    npm  update 
  5. Run the application
    node app.js

Documentation

Folder Structure

Layout

The Layout is heart of the nooljs project. Each page/module of the application can be defined as layout. It should be keep inside the layout folder.

    <nl-template id="store-edit-template" nl-permission="store-edit" nl-parent="main-content" >
    </nl-template>
    <nl-server-script>
    </nl-server-script>
   <nl-client-script>
     

The layout file contains three parts :

nl-template

    <nl-template id="store-edit-template" nl-permission="store-edit" nl-parent="main-content" >
      ... your html code for this template here .....
    </nl-template>
     

Template load event (nl-load)

This nl-load event will be fired after loading the template (nl-template). This is client side event. This will be useful to set any default values to the template after loading the template into the page.
    <nl-template id="store-edit-template" nl-load="loadData"  nl-permission="store-edit" nl-parent="main-content" >
      ... your html code for this template here .....
    </nl-template>
     
            
              <nl-client-script>
                {
                  loadData:function ($scope)
                  {
                  console.log(" enter assignDefaultAccount  function ");
                     if($scope.accounts && $scope.accounts.length > 0)
                	 {
                	  console.log(" enter assignDefaultAccount  function  assigen Account "+  $scope.accounts[0]);
                		$scope.$root.account = $scope.accounts[0];
                	 }
                  }
                  }
              </nl-client-script>
            
          

Getting data from database ( nl-db-data )

Getting the data from database/server and injecting into HTML template can be easily done without writing code or with minimum code. Nooljs will do all the magic of executing database query, passing the parameter between client and server, getting the result from server, and binding to the HTML template. It is designed to support any type of database or file system.

           <ion-list nl-db-data="exec Nodejs_GetUserAccountWithStore {{user.UserId}}"  nl-db-model="accounts" 
           nl-client-post-data="assignDefaultAccount"   nl-websocket ="false" >
        <ion-item ng-repeat="x	in accounts" menu-close >
         <span nl-click-redirect="{'url':'store-edit-template' ,  'params':{'AccountKey':'account.AccountKey', 'StoreId':'x.StoreId'}}" >
         {{x.StoreName}}  
         </span>
		   <button class="button button-clear"  
		   nl-click-redirect="{'url':'store-times' ,  'params':{'AccountKey':'account.AccountKey', 'StoreId':'x.StoreId'}}" >Store time
		   </button>
        <ion-item>
		    </ion-list>
        

Getting data from server (nl-server-data )

nl-server-data is similar to the nl-db-data, but it is advanced and flexible method to injecting the server side data into HTML template.

           <ion-list nl-db-data="validateLogin"  nl-db-model="accounts" nl-client-post-data="assignDefaultAccount"   
           nl-websocket ="false" >
        <ion-item ng-repeat="x	in accounts" menu-close >
         <span nl-click-redirect="{'url':'store-edit-template' ,  'params':{'AccountKey':'account.AccountKey', 'StoreId':'x.StoreId'}}" >
         {{x.StoreName}}  
         </span>
		   <button class="button button-clear"  
		   nl-click-redirect="{'url':'store-times' ,  'params':{'AccountKey':'account.AccountKey', 'StoreId':'x.StoreId'}}" >
		   Store time
		   </button>
        <ion-item>
		    </ion-list>
        
      	
      		<nl-server-script>
{
  validateLogin:
  {
       model:"item",
	server:function($scope)
	{
	 // $scope contains all the input values and add return values in to the scope  variable
	   // place server  side code here
	   // return  true if you want to execute db and post functions 
	   //return false  if you want to skip execution of  rest of functions
		return true;
		  
	},
        db:
	{
		query:"procedure=usp_LoginUser;userName=VarChar(255):{{login.username}},password=VarChar(255):{{login.password}} ,
		applicationName=VarChar:'StoreAdmin',clientIp=VarChar:'',userAgentString=VarChar:'' ",
		resultType:"single"
	}
	post:function($scope)
	{
	   // place  post server  side code here 
	   // $scope contains all the result from "server" and db functions.
	   // you can modify "server" and "db" results here.
	},
  }
}
</nl-server-script>
      	
      

Execution flow : server() --> db() --> post() -->nl-client-post-data ( client side)

Executing click event in the server side ( nl-server-click )

The nl-server-click attribute uses for the firing the click event at server side.

   	
   		  <button  id="category-edit-save"  nl-server-click ="saveCategory"
	 nl-redirect="{'url':'category-template', 'cond':'categorySaveResult.Status == 0', 'params':{'AccountKey':'account.AccountKey'}}"  >
		 save
		</button>
   	
   
   	
   		<nl-server-script>
{
  saveCategory:
  {
	model:"categorySaveResult",
	db:
	{
		query:"exec [usp_SaveCategory] {{AccountKey}} , {{category.CategoryId}},  'null', {{category.CategoryName}} ,  
		{{category.Description}} ",
		resultType:"single"
	}
  }
}
</nl-server-script>

   	
   

Execution flow : server() --> db() --> post() -->nl-client-post-data ( client side) --> nl-redirect

Executing click event at Database ( nl-db-click )

The nl-db-click is similar to the nl-server-click but you can directly specify database query.

   	
   		  <button  id="category-edit-save"  
   		  nl-db-click =""exec [usp_SaveCategory] {{AccountKey}} , 
   		  {{category.CategoryId}},  'null', {{category.CategoryName}} ,  {{category.Description}} "
	 nl-redirect="{'url':'category-template', 'cond':'categorySaveResult.Status == 0', 'params':{'AccountKey':'account.AccountKey'}}"  >
		 save
		</button>
   	
   

Redirect Event (nl-click-redirect)

   	
   	<button   nl-click-redirect="{'url':'category-template', 'params':{'AccountKey':'account.AccountKey'}}">Items</button<
   	
   

Login Process at server (nl-server-login)

The nl-server-login attribute is used for the login process. It is similar to the nl-server-click.

       		
       		    <button  nl-server-login="validateLogin"
			 nl-redirect="{'url':'main-template'}"  id="login-submit">
  Login
</button>	
       		
       	

The UserId field should be defined in cofig/config.json file. if userId value is grater than zero then login is successful and direct to the new template given in nl-redirect attribute.

       		
       		  <nl-server-script>
{
  validateLogin:
  {
	server:function($scope)
	{
		if(!$scope || !$scope.login || !$scope.login.username || !$scope.login.password )
		{
		     $scope.$root._error = {code:"INVALID_USER", message:"Invalid user information."};
			 return false;
		}
		return true;
		  
	},
    db:
	{
		query:"procedure=usp_LoginUser;userName=VarChar(255):{{login.username}},password=VarChar(255):{{login.password}} ,
		applicationName=VarChar:'StoreAdmin',clientIp=VarChar:'',userAgentString=VarChar:'' ",
		resultType:"single"
	}
    post:function($scope){
        // code for the post longin
        
        //return false for the failure
        return true;
    }
  }
}
</nl-server-script>

Login using Database (nl-db-login)

The nl-db-login is similar to the nl-server-login, but the database query can be specify directly without creating server side functions.

       		
       		    <button  nl-db-login="procedure=usp_LoginUser;userName=VarChar(255):{{login.username}},
       		    password=VarChar(255):{{login.password}} ,applicationName=VarChar:'StoreAdmin',clientIp=VarChar:'',
       		    userAgentString=VarChar:'' "
			 nl-redirect="{'url':'main-template'}"  id="login-submit">
  Login
</button>	
       		
       	

Permission (nl-permission)

The nooljs uses permission based authorization. The nl-permission attribute contains the name of the permission. It should be defined start of the template file with nl-template attribute. If given user does not have permission for given name then this template won't be loaded into the client. If nl-permission is empty then this template is public template.

   	
   	   <nl-template id="main-template" nl-permission="main" nl-parent="top-content">	
   	
   

All the permissions for this application can be load from file or database. The config/config.json defines the connection to load all the permissions for this application.

Sample config/config.json file

   	
   	   {	"userid" : "UserId",
  		"sessionTimeoutMinutes":60,
  		"logout":"login",
 		"defaultConnection": "sqlConn",
 		
"permission": { "connection":"jsonFile", "query" : "config/permision.json", "errorMessage": " You do not have permission to view this session." }
}

Sample permission.json file

   	
   	[ {	"userKey":"RoleName",
		"userValue" :"Admin",
		"permission" :"*"
	},
   	{ 	"userKey": "RoleName",
    		"userValue" :"StoreUser",
		"permission" :["main", "item", "category", "store","store-edit",
				"item-edit", "category-edit", "store-times" , "store-times-edit"]
   	},
    	{ 	"userKey": "RoleName",
    		"userValue" :"StoreManager",
		"permission" :["item", "category","store", "item-edit", "category-edit", "store-edit"]
   	}
   ]
   	
   

Default template (nl-default-template)

   	
   	   <ion-content id="main-content" nl-default-template="store-template">
   	
   	

Switching between Express and Socket-io

The switching between Express and Socket-io is really easy using nooljs framework. Even you can easily mix both frameworks within application.

client.js( inside public/js/client.js )

    		
    		var app = angular.module('myApp', ['nooljs', 'ionic']);

		app.run(['nlUtil', function (nlUtil) {
			nlUtil.useWebsocket(true);
		}]);

    		
    	

Turn off or turn on socket-io for the given data/layout injection

    		
    	  <ion-list nl-db-data="exec Nodejs_GetUserAccountWithStore {{user.UserId}}"  nl-db-model="accounts" 
           nl-client-post-data="assignDefaultAccount"   nl-websocket ="false"  >		
    		
    	

Server Method

Executing the server method inside the any client side JavaScript function is really easy.

index.html

   	
   <body ng-controller="myController">this is test
 <div id = "top-content" nl-default-template="login" nl-websocket ="false"> 
 </div>
 <input type="button" ng-click="onclick()" value="call server method" />
 <div>{{serverResult}}</div>
 </body>
   	
   

client.js ( client side JavaScript)

   	
   		app.controller("myController",['nlServerMethods', '$scope', function(nlServerMethods, $scope)
{
	$scope.serverResult= "my result";
	$scope.onclick= function(){
	 nlServerMethods.exec( "myMethods.myServerMethod1", "First", "parameter") 
		.then(function(data){
			$scope.serverResult = "data :" + data.data + " , error :"  + data.error;
		})
		.catch(function (err)
		{
			$scope.serverResult = " error :" + err;
		});
	};
}]);
   	
   

Server method should be inside /ServerMethod folder (/ServerMethod/myMethods.js)

   	
   		{
	myServerMethod1:
	{
		"permission":"myServerMethod1", 
		"method":function( name, value){
			return "hello - from method 1 " + name + " " + value;
		}
	},
	myServerMethod2:
	{
		"permission":"myServerMethod2",
		"method":function( name){
			return "hello -- from method 2 " + name ;
		}
	}
}
   	
   

Data Connection

The development of complex data driven application can be done easily using the nooljs framework. Nooljs is design to support all kinds of database. It is currently support Ms-sql, Mysql, Mongodb, Postgresql, and Json file. Other data bases will be supported very soon.

All the connection strings are defined in the config/connection.json file. The default connection for the application is defined in the config/config.json file.

Ms-sql

Thanks to Seriate for creating wonderful Microsoft SQL Server cross platform node module.

Using stored procedure:

    	
    	 " procedure=[usp_SaveStoreTime];StoreId=VarChar(50):{{StoreId}} ,StoreOperationTimeId=VarChar(50):{{StoreTime.StoreOperationTimeId}},IsDate=VarChar(50):{{StoreTime.IsDate}},IsSunday=VarChar(50):{{StoreTime.IsSunday}},IsMonday=VarChar(50):{{StoreTime.IsMonday}},IsTuesday=VarChar(50):{{StoreTime.IsTuesday}},IsWednesday=VarChar(50):{{StoreTime.IsWednesday}},IsThursday=VarChar(50):{{StoreTime.IsThursday}},IsFriday=VarChar(50):{{StoreTime.IsFriday}},IsSaturday=VarChar(50):{{StoreTime.IsSaturday}},Date=VarChar(50):{{StoreTime.Date}},OpeningTime=VarChar(50):{{StoreTime.OpeningTime}},CloseTime=VarChar(50):{{StoreTime.CloseTime}}"
            	
    	
    

Using query string :

    	
    	  "select * from stores where storeid =@StoreId and StoreOperationTimeId=@StoreOperationTimeId;StoreId=VarChar(50):{{StoreId}} ,StoreOperationTimeId=VarChar(50):{{StoreTime.StoreOperationTimeId}}"
        	
    	
    

Mysql

Thanks to mysql for creating wonderful Mysql cross platform node module.

   	
  <nl-template id="mysql-template"  nl-parent="mysql-content">
    <h1>my sql data</h1>
    <ion-list nl-server-data="getData" >
        <ion-item class="item" ng-repeat="x	in models">
           {{x.rowidx}} - {{x.name}} - {{x.description}}
      </ion-item>
    </ion-list>
</nl-template>
<nl-server-script>
    {
        getData:
        {
            model:"models",
            db:
            {
                query:"select rowidx, name, description, isactive  from demo.test where isactive  =?;[0]",
                connection:"mysqlConnection"
            }
        }
    }
 </nl-server-script>
   	
   

Mongodb

Thanks to mongodb for creating wonderful Mongodb cross platform node module.

   	
   		<nl-template id="mongodb-template"  nl-parent="mongodb-content">
    <h1>mondodb sql data</h1>
    <ion-list nl-server-data="getData" >
        <ion-item class="item" ng-repeat="x	in models">
           {{x.id}} - {{x.name}}
      </ion-item>
    </ion-list>
</nl-template>
<nl-server-script>
    {
        getData:
        {
            model:"models",
            db:
            {
                query:"cols=test;fun=find;params={\"active\":1}",
                connection:"mongodbConnection"
            }
        }
    }
</nl-server-script>
   	
   

Postgresql

Thanks to pg for creating wonderful Postgresql cross platform node module.

   	
  <nl-template id="postgresql-template"  nl-parent="postgresql-content">
    <h1>postgre sql data</h1>
    <ion-list nl-server-data="getData" >
        <ion-item class="item" ng-repeat="x	in models">
           {{x.id}} - {{x.name}}
      </ion-item>
    </ion-list>
</nl-template>
<nl-server-script>
    {
        getData:
        {
            model:"models",
            db:
            {
                query:"select name, active, id from tblname where active  =$1;[0]",
                connection:"postgresqlConnection"
            }
        }
    }
</nl-server-script>
   	
   

Support or Contact

If you need any help or bug fixing, please contract to cgkrish@hotmail.com