Skip to content
Vyacheslav edited this page Jun 26, 2015 · 15 revisions

Overview

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:

  1. - name of the area to which the component will belong;
  2. - name of custom html tag for component.

For instance:

yo jasper:component shop order-list

After 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

Structure of the component 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.

Configuration

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 */
  
}

templateFile (required)

Each component must have a template file. The content of this template will rendered in component tag.

type (required)

Specifies a type of jasper application parts. For components it always component.

ctrl

Specifies a controller of the component. If undefined - component will without logic, just template.

attributes (legacy)

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:

  1. Bind as expression result (angularjs '=' binding) - by default. Expression passed to the attribute evaluates, and result of that will pased to component property.
  2. Bind as plain text (angularjs '@' binding). Specify :text after attribute name. For instance attributes="heading:text".
  3. Bind as expression (angularjs '&' binding). Specify :expr after attribute name. Uses for creating component event model. For instance attributes="on-click:expr".

properties

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.

events

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).

template

Specifies inline template of the component.

transclude

The same as Angular's transclude property. Transcludes the content of component.

require

Mark component as required of another component. Almost the same as Angular's 'require' property.

Component's controller

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:

initializeComponent

Jasper invokes this method when all controller's attribute bindings are done. You can place any component initialize logic here

destroyComponent

Jasper invokes this method when component removes from the DOM. You may place any cleanup code here.

link

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.

Component's template

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.

Stylesheets

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.

Clone this wiki locally