AngularJS + Traceur + ES6

Introduction

ES6 is something cools and you can write java like script in browser. And AngularJS is also cool but when it getting bigger, the problems is there because it looks mess and dirty and needs to find a way to solve the messy problems that occurs in big AngularJS. There is the reason why I tried AngularJS+ES6. I have write it down the things I have tried when I was playing with it. Hope it will help you.

Installation

Install traceur by npm is the best way.

npm install -g traceur

# Build something simple first

index.js and index.html are code as below.

'use strict';

class My {
    constructor($scope) {
        this._scope = $scope;

        this.hello = "hello hoge";
    }

    getMessage() {
        return "hoge message";
    }
}

angular.module("myapp",[])
    .controller("myCtrl", [ "$scope" ,My]);

 

<html ng-app="myapp">
<head>
    <title></title>
    <script src="http://google.github.io/traceur-compiler/bin/traceur.js"></script>
</head>
<body ng-controller="myCtrl as m">
    <div ng-bind="m.getMessage()"></div>
    <div ng-bind="m.hello"></div>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
    <script type="text/javascript" src="build.js"></script>
</body>
</html>

Then, compile index.js and name output file as build.js.

traceur index.js --out build.js

As you can see build.js are ES5 js file and if you take a looks at safari, chrome, you are able to see the messages “hello hoge”.

Compile Multiple JS files

When design big, splits it into several files is compulsory. In this sample, I tried to put all es6 files into a folder and name it “es6”. File structure looks as below.

├ es6
│ ├ index.js
│ ├ apple.js
│ ├ banana.js
│ └ watermelon.js
├ build.js
└ index.html
<html ng-app="myapp">
<head>
    <title></title>
    <script src="http://google.github.io/traceur-compiler/bin/traceur.js"></script>
</head>
<body>
    <ul>
        <li><a ui-sref="banana">Banana</a></li>
        <li><a ui-sref="apple">Apple</a></li>
        <li><a ui-sref="watermelon">Watermelon</a></li>
    </ul>
    

    <div ui-view></div>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
    <script type="text/javascript" src="dist/angular-ui-router.min.js"></script>
    <script type="text/javascript" src="build.js"></script>
</body>
</html>
'use strict';
/*jshint esnext: true */
/*global angular: false */

import Banana     from "./banana.js";
import Apple      from "./apple.js";
import Watermelon from "./watermelon.js";


angular.module("myapp",["ui.router"])
    .config(function($stateProvider, $urlRouterProvider) {
        $urlRouterProvider.otherwise("/banana");

        $stateProvider
            .state('banana', {
                url: "/banana",
                controller: Banana,
                controllerAs: "vm",
                template: "<div ng-bind='vm.hello'></div>",
            })
            .state('apple', {
                url: "/apple",
                controller: Apple,
                controllerAs: "vm",
                template: "<div ng-bind='vm.hello'></div>",
            })
            .state('watermelon', {
                url: "/watermelon",
                controller: Watermelon,
                controllerAs: "vm",
                template: "<div ng-bind='vm.hello'></div>",
            });
    });

Watermelon.js and banana.js are similar to apple.js. Only hello variables are different.

'use strict';

class Apple {
    constructor() {
        this.hello = "hello this is Apple";
    }
}

export default Apple;

Finally, compile it.

traceur es6/* --out build.js

All es6 js files are kept in es6 folder, traceur can debug them by set scripts path to es6/*.

Where is scope?

At the first example I showed, scope have been declared but never been used. In case above, both of two this or $scope are works well. But as Angular2 are stop using $scope, and in $scope are not good looks with OOP design, $scope is not good idea anymore.

Reference Site

http://victorsavkin.com/post/99998937651/building-angular-apps-using-flux-architecture
http://www.sitepoint.com/writing-angularjs-apps-using-es6/
https://github.com/mvolkmann/todo-es6

Advertisements

Bugs of `instanceof` and `iFrame`

Checking either the objects is Array or Objects is a very common job in nowadays. For the most common way is using `instanceof`

myArr instanceof Array   // if myArr is array return true

It works perfect in most way, EXCEPT when you are using it inside iFrame. Multiple frame in single page will cause instanceof to detect Array as Object. It is absolutely pain…

Solution

Yet, you can still checking Array inside iFrame without using instanceof by Object.prototype.toString.call method. It will returned ‘[object Array]’ if myArr is Array.

 Object.prototype.toString.call(myArr) === '[object Array]' 

If you want to know more about the bugs, check it out kangax blogs. This site is more informative on it.

Installing Haskell Snap web framework in Homestead, Vagrant

Whole process of installing is not difficult compare to others language and framework. Every information needed is almost written in reference in clearly way. Even though I came across with the libgmp.so problem, it is not really a big deal and can be easily solved by apt-get. In this article, I am going to share my experience on how I installed snap into my Homestead.

Workflow

  • Installing Haskell 7.8.3 in Homestead
  • Installing Snap by Cabal
  • Make http://localhost:8080 work in Mac browser
  • Run Snap Server

Installing Haskell 7.8.3 in Homestead

Document is clear enough, there are three installing methods, community-supported version, Generic Linux binary and build from source. I choose Generic Linux binary. Here’s how I installed it.

sudo apt-get install libgmp3c2 freeglut3 freeglut3-dev -y
wget http://www.haskell.org/platform/download/2014.2.0.0/haskell-platform-2014.2.0.0-unknown-linux-x86_64.tar.gz
sudo mv haskell-platform-2014.2.0.0-unknown-linux-x86_64.tar.gz /temp_haskell.tar.gz
cd /
sudo tar xvf temp_haskell.tar.gz
sudo /usr/local/haskell/ghc-7.8.3-x86-64/bin/activate-hs

As libgmp3 is not installed in my Homestead, I tried to install it by apt-get install.

If you are using Ubuntu 14.04, it is even more simple to installed by.

sudo apt-get install haskell-platform

You can checked if it is worked by ghci command. Simple right!

Installing Snap by Cabal

Snap is even more easier if you are using Cabal to install. Before install snap, cabal ask me to update cabal-install. Then only I install snap by Cabal.

cabal update
cabal install cabal-install
cabal install snap --force-reinstalls

Install is done. I checked if it is worked by create a new snap project.

mkdir pizzahouse
cd pizzahouse
~/.cabal/bin/snap init

If there is file are generated, it means Snap is installed. Yeah!

スクリーンショット 2014-10-27 午前1.56.14

Make http://localhost:8080 work in Mac browser

This is the most troublesome part of the whole work.First, I have to create a new virtual host in nginx and proxy port 8080 used by Snap to port 80.

Inside folder /etc/nginx/sites-available, I created a new virtual host file named “localhost” and wrote following code.

server {
    listen 80;
    server_name localhost;
    root /home/vagrant/Code/haskell;

    charset utf-8;
    access_log off;
    error_log  /var/log/nginx/localhost-error.log error;

    try_files $uri/index.html $uri @app;

    location @app {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://127.0.0.1:8080;
    }

    location ~ /\.ht {
        deny all;
    }
}

Then, symlink sites-available/localhost file and sites-enabled/localhost file.

ln -s /etc/nginx/sites-availble/localhost /etc/nginx/sites-enabled/localhost

After configuration and symlink is finished, I restarted nginx.

Run Snap Server

Compile the file and start the server at port 8080. Then, every things worked like magic, http://localhost:8080 is working in local browser.

cabal install
~/.cabal/bin/pizzahouse -p 8080

Thank you for reading.

Building one page site by using AngularJS and Laravel… mostly AngularJS

It is the site I working on currently and it is using AngularJS 1.2.26 and Laravel 4.2.9

 

I am thinking to renew my site with some new cool technology and here’s come, AngularJS. What is the charming point of AngularJS?

HTML is great for declaring static documents, but it falters when we try to use it for declaring dynamic views in web-applications. AngularJS lets you extend HTML vocabulary for your application. The resulting environment is extraordinarily expressive, readable, and quick to develop. – by angularjs.org

Be honest, I don’t quite understand what it’s talking about. I looked through many sites, blogs, and I got a better and understandable answer,

AngularJS is a powerful JavaScript framework for building one page web application.  –  by edisonthk

Preparation & Installation

I am going to using laravel for my backend framework, server. Version is 4.2.9

laravdel

Server is getting worked in few minutes.

composer create-project laravel/laravel --prefer-dist
Configuration app/local/database.php
php artisan migrate

and AngularJS for my frontend framework. Version is 1.2.26

angularjs.jpeg

Download from https://angularjs.org/ and locate it in public/js folder.

Coding in Laravel

Let’s begin coding, first begin with Laravel. Laravel handle all kinds of data and response in json. Open app/routes.php and configure the routing.

<?php

// Response in JSON
Route::controller('/json/tag','TagController');
Route::resource('/json/snippet','SnippetController');

// Response for AngularJS
Route::get("/",function(){
  return View::make("base");
});

AngularJS also able to handle routing, I will show it later on. Now, open app/views/base.php and we are going to coding it.

I got a static parts, navigation bar, header and dynamic parts, snippets list and article selected. In code below, nav tag is the static part and ng-view is dynamic parts.

<html lang="ja">
	<head>
		<meta charset="utf-8">
		<!-- <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=2.0,user-scalable=no"> -->
		<meta name="format-detection" content="telephone=no">
		<title>Codegarage</title>


		<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">
		<link rel="stylesheet" type="text/css" href="/css/font-awesome.min.css">
		<link rel="stylesheet" type="text/css" href="/css/common.css">

		<!-- Angularjs library -->
		<script type="text/javascript" src="/angular-libs/angular.min.js"></script>
		<script type="text/javascript" src="/angular-libs/angular-route.min.js"></script>

		<!-- Angularjs Application -->
		<script type="text/javascript" src="/angular-js/app.js"></script>
		<script type="text/javascript" src="/angular-js/controllers.js"></script>
		
	</head>
	<body>
		<!-- static part -->
		<nav>
			<div class="container">
				<div class="row">
					<div class="col-md-12">
						<h1 id="logo"><a href="/">Codegarage</a></h1>
					</div>
				</div>
			</div>
		</nav>
		

		<!-- dynamic part -->
		<div ng-view></div>
	</body>
</html>

In angularJS tutorial, I found out that angular js able to handle routing and multiple views. You can check it out at https://docs.angularjs.org/tutorial/step_07. I am going to adapt it in my site. ng-view on above, will be rendered by other html by angularJS.

Next, prepare data. Open app/controllers/SnippetController.php and return data in json.

<?php

class SnippetController extends BaseController {

	/**
	 * Display a listing of the resource.
	 *
	 * @return Response
	 */
	public function index(){

		$snippets = array();
		foreach (Snippet::all() as $snippet) {
			$temp = $snippet->toArray();
			
			array_push($snippets, $temp);
		}

		return Response::json($snippets);
	}	

And app/controllers/SnippetController.php also do the same by return data in json.

Coding in AngularJS

It is my file structure, I have prepare three angular folders in public for html, javaScript and library respectively.

スクリーンショット 2014-10-03 午前3.02.49

 

First, I begin with angular-js/app.js

var codegarageApp = angular.module('codegarageApp',['ngRoute','ngSanitize', 'snippetContollers']);

codegarageApp.config(['$routeProvider',
	function($routeProvider) {
		$routeProvider.
			when('/snippets', {
				templateUrl: '/angular-html/index.html',
				controller: 'SnippetListCtrl'
			}).
			otherwise({
				redirectTo: '/snippets'
			});
	}]);

I have import two plugins, ngRoute and ngSanitize. ngRoute is used for routing and handle multiple views. ngSanitize is used for safe html template, if you are using ng-bind-html, it is required to import this plugin for binding safety html.

Then, angular-js/controllers.js

var snippetContollers = angular.module('snippetContollers', ['ngSanitize']);

snippetContollers.controller('SnippetListCtrl', ['$scope','$http',function($scope, $http){

	$http.get('/json/snippet').success(function(data) {
		$scope.snippets = data;
	});

	$scope.article = "<p>hello! This is html.<p>;

}]);

Retrieve data from SnippetController by request /json/snippet and output it to $scope.snippets. Best things, it will decode json to object automatically.

Last thing, angular-html/index.html

<div class="wrapper">
	<div class="container">
		<div class="row">
			<div class="col-md-6">
				<!-- BEGIN: snippets list -->
				<div id="snippets">
					
					<div ng-repeat="snippet in snippets" class="single-snippet">
						<div class="title">
							<p><a href="/snippet/{{snippet.id}}">{{snippet.title}}</a></p>
							
						</div>
						<div class="meta">
							<div class="tags-group">
								
								<span ng-repeat="tag in snippet.tags" class="tag">{{tag.name}}</span>
								
							</div>
							<div class="datetime">Updated at {{snippet.updated_at}} </div>
						</div>			
					</div>
					
				</div>
				<!-- END: snippets list -->
			</div>
			<div class="col-md-6">
				<div ng-bind-html="article"></div>
			</div>
		</div>
	</div>
</div>

Tips of validation in Laravel 4

Laravel provide a very helpful feature on validation. If you are still writing somethings like this…

if(Input::get("password") != Input::get("password_confirmation")){
     return Redirect::back()-&gt;with("error","password confirm is not matched");
}

I think it is time for you to understand how powerful Laravel is.

Confirmation

Mail, password confirmation can be done easily by validation rules.

$rules = array(
		"password" 				=&gt; "required|confirmed",
		"password_confirmation"	=&gt; "required",
	);

$validator = Validator::make(Input::all(), $rules);
&lt;form action="post"&gt;
    &lt;input type="password" name="password"&gt;
    &lt;input type="password" name="password_confirmation"&gt;
&lt;/form&gt;

For mail confirmation, replace password_confirmation to email_confirmation.

Unique value

Let’s say, “name_col” must be unique and there is no duplicate.

+----+-------------+
| id | name_col    |
+----+-------------+
|  1 | Steve       |
|  2 | John        |
+----+-------------+
$rules = array(
		"name_col" =&gt; required|unique:mytable",
	);

$validator = Validator::make(Input::all(), $rules);

Regular Expression

Another powerful feature in Laravel 4 validation is regular expression. Following sample show the Katagana regular expression.

$rules = array(
		'katagana'      =&gt; 'regex:/^[ァ-ヶー]+$/',
	);

$validator = Validator::make(Input::all(), $rules);

Custom Error Message

You would like to have your own error message, open app/lang/en/validation.php and configure. Let’s say, you want to modify “confirmation” error message.

"confirmed" =&gt; "Hey! :attribute is not matched", 

Quick guide on installation Laravel Homestead in Windows 8

Updated: 2014-12-5 Lastest version of Homestead is not working in this article. But it is still possible to install Homestead into your windows environment by checkout to old version of Homestead. I will show you how to do it in this article.


Latest version of Vagrant 1.6.3 and VirtualBox 4.3.14 seems to get working in Windows environment. In this article, I want to tell you that you are able to install Laravel Homestead in Windows within 20 minutes (15 minutes for downloading Vagrant box and time for toilet). Well, hope you are able to get every work in 20 minutes.

1. Download the required software

Download all the software on below, we required it when installing Homestead and Laravel

putty and puttygen both softwares are needed. You are able to download on same website, same page. After downloading, install VirtualBox and Vagrant.

2. Adding Homestead Vagrant box

After Vagrant is installed, open the command prompt and execute following commands to adding Homestead Vagrant Box. It take quite a long time to download. For me, I take almost 15 minutes to download.

Continue reading

Handle Table Relationships by Eloquent in Laravel 4

I summarize the things written in Laravel Docs so it almost the same things.

# One to One

In table below, every user has one phone. Column phone_id represent the data in phones and all phone_id stored in users table is unique and no repeat.

スクリーンショット 2014-08-21 午後7.48.58

In app/models/User.php, it should looks like this. In default, there is no User.php and you have to create by yourself.

class User extends Eloquent {

    public function phone()
    {
        // 1st parameter is eloquent class name
        // 2nd parameter is foreign key
        // 3rd parameter is local key in "users" table
        return $this->hasOne('User','user_id','id');
    }

}

For phones table

class Phone extends Eloquent {

    public function user()
    {
    	// 1st parameter is eloquent class name
        // 2nd parameter is foreign key
        // 3rd parameter is local key in "users" table
        return $this->belongsTo('User','user_id','id');
    }

}

In migrations file, it should looks like this.

Continue reading