-
Notifications
You must be signed in to change notification settings - Fork 1
Components
Component - it's a reusable block of your application. Components allows you to extend html markup with your own HTML elements. Components allows you to encapsulate your markup, logic, styles and reuse it in any part of your application.
For instance your page markup may be following:
<order-list>
<order-list-item for="item" ng-repeat="item in vm.items"></order-list-item>
</order-list>order-list and order-list-item - is a components. When you want to extend your markup - you need to create component. Using components in your templates - makes your view layer more declarative and clear.
To create component type:
yo jasper:component <AREANAME> <COMPONENT-TAG-NAME>Where:
- - name of the area to which the component will belong;
- - name of custom html tag for component.
For instance:
yo jasper:component shop order-listAfter that component will be created in shop area folder. When you are done run grunt to build application and you can use component as custom HTML tag: <order-list></order-list>
In application project component represents as folder
-
_definition.json- file that store component configuration -
component-name.html- template for component -
ComponentName.ts- typescript class with with component behaviour -
component-name.css- stylesheets for the component
Thus each component has all necessary to be reused in any part of your application.
Each component need to be configured. _definition.json contains a JSON configuration.
{
"templateFile": "catalog-sets.html",
"type": "component",
"ctrl": "app.shop.components.CatalogSets",
"properties": "category filters",
"events": "click update"
/* other properties */
}Each component must have a template file. The content of this template will rendered in component tag.
Specifies a type of jasper application parts. For components it always component.
Specifies a controller of the component. If undefined - component will without logic, just template.
Specifies component external interface (works over AngularJS isolate scope bindings). Attributes is a way to customize component properties.
It's a space separated string, each word specify an attribute name of component tag. Value of each attribute binds to property of component class instance.
There are three attribute binding:
- Bind as expression result (angularjs '=' binding) - by default. Expression passed to the attribute evaluates, and result of that will pased to component property.
- Bind as plain text (angularjs '@' binding). Specify
:textafter attribute name. For instanceattributes="heading:text". - Bind as expression (angularjs '&' binding). Specify
:exprafter attribute name. Uses for creating component event model. For instanceattributes="on-click:expr".
Properties is more efficient way to define component's external properties bindings. This property may be a space separated string or an array with properties names. You can pass this properties in a 2 way:
- Specify attribute name to bind the text in attribute;
- Specify attribute name as `bind-{name}' to bind an expression.
For instance, you have an a component MyButton with property color:
module controls {
export class MyButton {
color: string;
text: string;
// other props
}
}And definition:
{
"ctrl": "controls.MyButton",
"properties": "color text",
"templateFile": "my-button.html"
}Now you can pass this properties like:
<my-button color="red" bind-text="vm.buttonText"></my-button>In this case property color will be binded as red string, and property text will has value of vm.buttonText.
Using this property you can define component's external events. This property may be a space separated string or an array with event names. After define an event you can use it with on-{event} attribute:
{
"ctrl": "controls.MyButton",
"properties": "color text",
"events": "click mousedown",
"templateFile": "my-button.html"
}Usage:
<my-button on-click="vm.submit()" on-mousedown="vm.mousedown($event)" color="red" bind-text="vm.buttonText"></my-button>Jasper will pass to component's controller an special object EventEmitter. Inside MyButton you can use it to emit an event:
module controls {
export class MyButton {
// events:
click: jasper.core.IEventEmitter;
mousedown: jasper.core.IEventEmitter;
// other props
propagateMouseDown(e) {
this.mousedown.next(e);
}
}
}Parameter in the next function will be allowed as $event (see sample above).
Specifies inline template of the component.
The same as Angular's transclude property. Transcludes the content of component.
Mark component as required of another component. Almost the same as Angular's 'require' property.
Controller allows you to create component logic in imperative style. Controller in jasper application represents as class. Instance of this class creates on every component usage in DOM. For instance:
module spa.shop.components {
export class OrderList {
// inject services to the component
static $inject = ['OrderService', '$globalEvents'];
items: models.OrderItem[] = [];
private subscription: jasper.core.ISubscription;
constructor(private orderService: services.IOrderService, private globalEvents: jasper.core.IGlobalEventsService) {
}
// component public method
setItems() {
this.orderService.getAllItems().then(items => {
this.items = items;
});
}
// invokes by jasper, when components associates with DOM element and ready to work
initializeComponent() {
this.setItems();
// subscribe on global application event
this.subscription = this.globalEvents.subscribe('orderItemsChanged', () => {
this.setItems();
});
}
// invokes by jasper, when components removes from DOM
destroyComponent() {
this.subscription.remove();
}
}
}Controller may have the following public method to handle own lifetime:
Jasper invokes this method when all controller's attribute bindings are done. You can place any component initialize logic here
Jasper invokes this method when component removes from the DOM. You may place any cleanup code here.
Jasper invokes this method when component associate with specific HTML element. If you would like to get HTMLElement reference, you can make it in this method:
module spa.shop.components {
export class OrderList {
/**
* Jasper invoke this method, during angular's link phase - when component associates with
* own html DOM element
*
* @element - html element
* @components - array or single components, that will be required by 'require' property of component definition
*/
link(element: HTMLElement, components: any){
// place your logic here
}
}
}Controller instance avaliable in template as vm property.
Template determines the appearance of your component. Template represents as HTML file. You can use any html processors (like jade), but templateFile must reference HTML template.
In your template you can access to the controller using vm property. For instance:
Controller
module spa.shop.components {
export class OrderList {
someProperty: string = 'hello world!';
}
}Template:
<p>
{{ vm.someProperty }}
</p>The result:
<p>
hello world!
</p>If you modify your controller properties and this changes will reflect to the view. Also you can use another components in your template:
<div>
<order-info for="order" ng-repeat="order in vm.orders"></order-info>
</div>Where <order-info> it's another component. So your application is assembled from multiple components.
To make sure that your component looks properly at different application contexts you need to create specific component styles. Component CSS file should contains styles for HTML nodes defined in template. That is, the styles should not affect on element of other components.
All styles of components will be referenced to the index.html page at build time.