ECMAScript 6 in action with the view
Last time (ECMAScript 6 in action with the inheritance and the models ) we’ve created an “humansView” quickly. Today we’re going to use Handlebars to make something more “à la Backbone”. Handlebars is a javascript templating library.
Modify bower.json
{
"name" : "es6-project" ,
"version" : "0.0.0" ,
"dependencies" : {
"uikit" : "~2.8.0" ,
"jquery" : "~2.1.1" ,
"handlebars" : "~1.3.0" ,
"traceur" : "~0.0.49"
},
"resolutions" : {
"jquery" : "~2.1.1"
}
}
We’ve had "handlebars": "~1.3.0"
(handlebars dependency). Now, type this command: bower update
.
Update collection.js
We need to add a toJson()
method to the collection, then we can pass simple json object to handlebars templates:
toJson () {
return this . models . map (( model ) => model . fields );
}
Create a component ViewModel: HumansList
You can delete js/app/views/humansView.js
, create a new directory: components
in js/app/views
with a new javascript file humans-list.js
:
es6-project/
├── node_modules/
├── public/
| ├── bower_components/
| ├── js/
| | └── app/
| | ├── core/
| | | ├── model.js
| | | └── collection.js
| | ├── models/
| | | ├── human.js
| | | └── humans.js
| | ├── components/
| | | └── humans-list.js
| | └── main.js
| └── index.html
├── .bowerrc
├── bower.json
├── package.json
└── app.js
with this content:
class HumansList {
view () { return `
< ul >
{{ # each humans }}
< li > {{ id }} {{ firstName }} {{ lastName }} < /li >
{{ /each} }
< /ul >
` ;}
constructor ( humansCollection ) {
humansCollection . addObserver ( this );
this . humans = humansCollection ;
this . template = Handlebars . compile ( this . view ());
this . el = document . querySelector ( "humans-list" );
}
render () {
this . el . innerHTML = this . template ({ humans : this . humans . toJson ()});
}
update ( context ) {
this . render ();
}
}
export default HumansList ;
Update main.js
import Human from './models/human' ;
import Humans from './models/humans' ;
import HumansList from './components/humans-list' ;
class Application {
constructor () {
$ ( "h1" ). html ( "E6 rocks!" )
var humans = new Humans ();
var list = new HumansList ( humans )
humans . fetch (). done (() => { /* get all humans from database */
if ( humans . size () == 0 ) { /* no human in database, then populate the collection */
var bob = new Human ({ firstName : 'Bob' , lastName : 'Morane' });
var john = new Human ({ firstName : 'John' , lastName : 'Doe' });
var jane = new Human ({ firstName : 'Jane' , lastName : 'Doe' });
/* save models */
bob . save (). done (
() => john . save (). done (
() => jane . save (). done (
() => humans . fetch (). done ( console . log ( humans )) /* fetch again */
)
)
);
} else { /* display humans */
console . log ( humans );
}
})
}
}
$ (() => {
new Application ();
});
We’ve changed:
import HumansList from './components/humans-list';
and var list = new HumansList(humans)
Last update
Modify index.html
, you have just to add handlebars reference: <script src="bower_components/handlebars/handlebars.min.js"></script>
:
<!DOCTYPE html>
<html>
<head lang= "en" >
<meta charset= "UTF-8" >
<title> es6-project</title>
<meta name= "viewport" content= "width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />
<link rel= "icon" sizes= "196x196" href= "html5.png" >
<meta name= "mobile-web-app-capable" content= "yes" >
<link rel= "stylesheet" href= "bower_components/uikit/dist/css/uikit.almost-flat.min.css" />
</head>
<body style= "padding: 20px" >
<h1></h1>
<humans-list></humans-list>
<script src= "bower_components/jquery/dist/jquery.min.js" ></script>
<script src= "bower_components/handlebars/handlebars.min.js" ></script>
<script src= "bower_components/traceur/traceur.js" ></script>
<script>
System . import ( 'js/app/main' );
</script>
</body>
</html>
Now you can refresh http://localhost:3000/ and you’ll get a list of humans (again).
Next time we’ll use Polymer instead of our “from scratch” viewmodel component.
You can find source codes here : https://github.com/js-experiments/es6-project
Have a nice day!