#FerrugemJS
###A simple library, reactive, conventional and non-intrusive!
FerrugemJS is inspired by Aurelia and React using Incremental DOM with a html template engine.
####No jquery required, only 2kB!

####Browser Support
 |  |  |  |  |  |
---|
Latest ✔ | Latest ✔ | 9+ ✔ | Latest ✔ | 6.1+ ✔ | Latest ✔ |
####examples
https://ferrugemjs.github.io/examples/index.html
####how to start:
clone
skeleton-typescript
####individual install
npm install ferrugemjs
jspm install npm:ferrugemjs
####initialization
eg. index.html file
<body>
<div app></div>
<script>
System.import("ferrugemjs");
</script>
</body>
FerrugemJS will look for the first page element with the attribute "app" to start the application and if not found it, will use the tag "body".
Just create app.ts files and app.html in the same directory of the index.html page.
If you want to modify the path of the init file just add this information to the app attribute as below:
<div app="other_path/init_app_file"></div>
####modules & custom tags
To create a module witch will be a custom tag do you need two files with same name(eg. "module-a.ts" and "module-a.html").
By convention FerrugemJS know that "module-a.ts" is a controller file and "module-a.html" is the view of it and you can easily import it into your main app html file or into other module and use as a component with a custom tag.
eg.
"module-a.ts" file.
export class ModuleA{
private title:string;
constructor(){
this.title = "test!";
}
}
eg. "module-a.html" file.
<template>
<h1>My First APP with ${this.title}</h1>
</template>
now, we can importe into other template
<template>
<require from="./module-a"></require>
<div>
<module-a title="new title!"></module-a>
</div>
</template>
###module lifecycle
*attached:
By implementing the method your module will be prompted for it once the html is in "DOM".
attached(){
console.log('im in DOM');
}
*detached:
By implementing the method your module will be prompted for it once your object is detached from "DOM".
detached(){
console.log('im out');
}
*set+attribute name:
By implementing the method with the module attribute in CamelCase format your module will be notified when there is any change to the way template attribute
setName(name:string){
this.name = name;
}
###one-way data binding
When you set the 'value=${name}' in a input component it will set "value" attribute in element after a controller refresh.
<template>
<div>
<h2>Hello World, ${this.name}</h2>
<input value="${this.name}"/>
</div>
</template>
###event binding
When you set the "keyup.bind" in a input component it will change the "name" attribute in controller after a keyup event.
<template>
<div>
<h2>Hello World, ${this.name}</h2>
<input keyup.bind="this.name"/>
</div>
</template>
###manual event reactivity
<template>
<div>
<h2>Hello World, ${this.name}</h2>
<input change.trigger="this.manualChangeMethod"/>
<div>
</template>
export class HelloWorld{
private name:string;
private refresh:Function;
constructor(){
this.name = "";
}
manualChangeMethod(event):void{
this.name = event.target.value;
this.refresh();
}
}
###template stuffs
if,elseif,else
<template>
<div>
<if condition="this.name==='test'">
<span>name is test</span>
</if>
<if condition="this.name==='test'">
<span>name is test</span>
<else>
<span>I dont know you!</span>
</if>
<if condition="this.name==='test'">
<span>name is test</span>
<elseif condition="this.name==='test2'">
<span>ok, you are test2</span>
</if>
<if condition="this.name==='test'">
<span>name is test</span>
<elseif condition="this.name==='test2'">
<span>ok, you are test2</span>
<else>
<span>I dont know you!</span>
</if>
</div>
</template>
for each
<template>
<ul>
<for each="item in this.itens">
<li>${item.name}</li>
</for>
<for each="item,$index in this.itens">
<li>${$index} - ${item.name}</li>
</for>
</ul>
</template>
import other module
<template>
<require from="./example/hello-world"></require>
<div>
<h1>My First APP with ${this.title}</h1>
<hello-world name="C-3PO"></hello-world>
</div>
</template>
give an alias in module import statement.
<template>
<require from="./example/hello-world as sea-bienvenido"></require>
<div>
<h1>My First APP with ${this.title}</h1>
<sea-bienvenido name="C-3PO"></sea-bienvenido>
</div>
</template>
import a css file.
<template>
<require from="./hello-world.css!"></require>
<h1>My First APP with ${this.title}</h1>
</template>
embed a style tag.
<template>
<style>
.especial-tag{
background-color:red;
}
</style>
<h1 class="especial-tag">My First APP with ${this.title}</h1>
</template>
change the css className
<template>
<style>
.my-custom-classname{
background-color:red;
}
</style>
<h3 class="my-custom-classname">My element with a custom className</h3>
</template>
change the css className with expression
<template>
<style>
.style1{
background-color:red;
}
.style2{
background-color:blue;
}
.style3{
background-color:green;
}
</style>
<h3 class="${'my-custom-classname '+this.customStyle}">My element with a custom className by expression</h3>
</template>
set where the content of element must be.
<template>
<h1>
<content></content>
</h1>
</template>
other template.
<template>
<require from="./example/hello-world"></require>
<div>
<hello-world>
Good night!
</hello-world>
</div>
</template>
import other library/script.
<template>
<require from="moment" type="script"></require>
<span>${moment().format('DD/MM/YYYY')}</span>
</template>
import other ui library as a namespace.
<template>
<require from="ui-vendor as ui" type="namespace"></require>
<div>
<span>using a ui library</span>
<ui:progress-bar></ui:progress-bar>
</div>
</template>
preserve a element instance.
<template>
<require from="./test-comp"></require>
<div>
<test-comp key:id="key_unique"></test-comp>
</div>
</template>
associete a controller method to DOM event.
<template>
<button click.trigger="this.showName">show my name!</button>
</template>
associete a controller method to DOM event with extra paramaters.
<template>
<button click.trigger="this.showName('test')">show my name!</button>
</template>
to access a camelCase method or attribute from template (use slashes '-').
<template>
<require from="./test-comp"></require>
<div>
<test-comp full-name="test"></test-comp>
</div>
</template>
associete a controller method to a custom element event.
<template>
<require from="./test-comp"></require>
<div>
<test-comp on-change-name.subscribe="this.showName"></test-comp>
</div>
</template>
composition.
<template>
<div>
<compose view="path_to_dinamic_module/module_to_loader"></compose>
</div>
</template>
multiples views to a view-model.
<template view-model="./universal-view-model">
<div>
<h1>VIEW ONE</h1>
<span>bla,bla,bla....</span>
</div>
</template>
<template view-model="./universal-view-model">
<div>
<h3>VIEW TWO</h3>
<p>lol lol lol</p>
<img src="logo.png">
</div>
</template>
template viewmodel-less.
<template no-view-model="true">
<h1>NO viewmodel</h1>
</template>