Skip to content

Composite

mr-mig edited this page Dec 13, 2014 · 2 revisions

What is 'composite'?

Composite is a mid-level building block for your app.
It is used to combine elements and other composite in a customized piece of UI.

It is represented by a custom tag in your markup:

<my-composite state="someState"></my-composite>

The API is pretty much the same, as of element.

How to reason about it?

  • Use it for a piece of the page, composed of low-level components.
  • Composite defines the relations between element states using links and channels

What is the difference between 'element' and 'composite'?

Roles:

  • Element can modify only it's internal state.
  • Composite makes elements talk to each other.

Portability:

  • Element is totally reusable between apps
  • Composite can be tightly bounded to the app

Functional:

  • Composite has access to channels and link.

Usage

Definition

yaf.composite({
  // String.
  // Composite tag name. Should be camelCase. The tag name in template will be 'my-composite'
  name: 'myComposite', 

  // String. 
  //The content of the associated style tag
  styles: require('./styles.css'),

  // String. 
  // The content of the associated template
  template: require('./template.html'), 

  // Map (String : Module|String).
  // The map of Alias Names and module objects to be used with composite's associated logic
  inject: {
     // AMD/CommonJS format, will inject module.exports as ComponentAliasName
     // It's the same as var ComponentAliasName = require('../some-other-component');
    'ComponentAliasName' : require('../some-other-component'),

    // Angular format, will inject MySuperDirective using angular's DI
    // Also, it will add the injected angular-module to dependencies 
    'MySuperDirective' : 'my-super-module',

    // Mixed Angular-CJS/AMD format
    'MyCjsDirective' : require('../path/to/angular-module').name
  },

  // Map (String : NonFunction)
  // The default state of the composite. Will be {} if not defined.
  // Will be created automatically if not linked in the template using 'state' attribute.
  state : {
    // Can be referenced inside the template using 'state.someValue'
    someValue: 'xxx'
  },
  
  // Object (String : NonFunction)
  // The default values for the composite options configuration. Will be {} if not defined.
  // Each field is mapped to HTML attribute.
  options : {
     // Can be overridden by DOM-element attribute 'maxlength'
     maxlength : 50
  },

  // Function.
  // The associated composites's logic. Will be called when DOM-element is attached to DOM and linked with it's state.
  ready: function(){
     
    // associated DOM-element
    this.element;

    // current linked state map
    this.state;

    // current parsed options map
    this.options;

    // the map of values, available in template. Defaults to {}
    this.templateScope;

    // the map of injected components 
    this.injector;

    // the injected component reference
    this.injector.ComponentAliasName;

    // Function.
    // the map of injected components 
    this.link;

    // Object.
    // Channels registry object
    this.channels;
    
    // Channel.
    // Getting channel from registry by channel name.
    this.channels.get('button-click')
  }
});

Simplest form

yaf.composite({
  name: 'myComposite',
  styles: require('./styles.css'),
  template: require('./template.html')
});

Conventions

  • Composite MUST have some state (controlled by framework, fallback to a default empty object state)
  • Composite MUST bind it's state to some namespace through HTML state attribute (controlled by user)
  • Composite CAN change the state of underlying elements directly or via link and channel
  • Composite CAN react on channel signals (controlled by framework)
  • Composite CAN omit channel binding through HTML channel attribute
  • Composite CAN provide the API by binding elements' state to it's own state (controlled by user)
  • Composite CAN be replaced by it's template in the resulting markup