Fragment & Activity component

Fragment and activity are using View and representing re-usable UI components.

Usage

Fragment and activity components are using View and representing re-usable UI components.

Activity component is same as Fragment but its definition is registered in activities array.

Fragment definition example

Meta.Fragment("com.example.todo", {

    //If to create shadow-root (default: true)
    shadowRoot: true,

    //Default view
    view: "com.example.todo",

    //Required modules to be imported
    import: ["example-list"],

    //Extends other fragments (inherit their definition)
    extends: ["com.example.list"],

    //View template bindings
    binding: {
        "ul li": $__repeat("tasks", {
            "@":        [
                $__attrIf("completed", "completed"),
                $__prop("task", "@key")
            ],
            ".task":    "task"
        })
    },

    //View event bindings
    events: {
        "click #add": function(ev){

            var value = this.$.todo.value;

            if(value != ""){
                this.provider.addTask(value);
                this.$.todo.value = '';
            }

        },

        "click ul li": function(ev){

            this.provider.toggleTask(ev.sender.task);

        },

        "click ul li .remove": function(ev){

            ev.stopPropagation();
            this.provider.removeTask(ev.sender.parentElement.task);

        }
    },

    //onCreate custom handler
    onCreate: function(self){

        //Create provider
        self.provider = new TodoProvider("com.example.simpleTodo");

        //Set model
        self.model.tasks = self.provider.tasks;

    },

    //onResume custom handler
    onResume: function(self){

        self.providerChanged = self.provider.on("changed", function(data){
            self.render();
        });

    },

    //onPause custom handler
    onPause: function(self){

        self.provider.off("changed", self.providerChanged);

    },

    //onRender custom handler
    onRender: function(self){

        console.log("Rendered");

    }

});

Fragment usage example

<meta-fragment name="com.example.todo" auto></meta-fragment>

Fragment definition properties

Fragment definition properties are used to configure fragment behaviour.

shadowRoot property

{
    shadowRoot: true
}

shadowRoot: boolean

Specifies if to create Shadow root.

Default: true

import property

{
    import: [ "fragment-a", "fragment-b" ]
}

import: array of string

List of modules which should be imported before fragment is initialized.

See Utilities / Import for module importing details.

extends property

{
    extends: [ "fragment-a", "fragment-b" ]
}

extends: array of string

Specifies list of other fragment from which definition will be merged.

Listed fragments must be imported or listed in import property or exception will be thrown.

Example:

Meta.Fragment("com.example.a", {
    
    view: "com.example.a",
    
    model: {
        x: 1
    }

});

Meta.Fragment("com.example.b", {

    view: "com.example.b"

});

Meta.Fragment("com.example.c", {

    extends: ["com.example.a", "com.example.b"],
    shadowRoot: false

});

Fragment com.example.c definition will be:

{
    view: "com.example.b",

    model: {
        x: 1
    },

    shadowRoot: false
}

model property

{
    model: {
        "key": "val"
    }
}

model: object

Default model object which will be bound to view's model property.

binding property

{
    binding: {
        ".selector": "model_property"
    }
}

binding: object

Template binding rules which will be passed to view's instance function.

events property

{
    events: {
        "click .button": function(ev){ //... }
    }
}

events: object

View event binding rules which will be bound to view's events property.

Note that view's eventsContext property is set to fragment instance.

onCreate property

{
    onCreate: function(self){
        //...
    }
}

onCreate: function(self)

Function which will be called when fragment is created.

See Fragment lifecycle for more details.

onReady property

{
    onReady: function(self){
        //...
    }
}

onReady: function(self)

Function which will be called when fragment is ready.

See Fragment lifecycle for more details.

onResume property

{
    onResume: function(self){
        //...
    }
}

onResume: function(self)

Function which will be called when fragment is resumed.

See Fragment lifecycle for more details.

onPause property

{
    onPause: function(self){
        //...
    }
}

onPause: function(self)

Function which will be called when fragment is paused.

See Fragment lifecycle for more details.

onRender property

{
    onRender: function(self){
        //...
    }
}

onRender: function(self)

Function which will be called when fragment's view has been rendered.

Custom method example

Define fragment:

Meta.Fragment("com.example.todo", {

    sayHello: function(name){
        alert("Hello " + name + "!");
    }

});

Create fragment:

<meta-fragment name="com.example.todo" id="my-fragment"></meta-fragment>

Call custom method:

document.getElementById('my-fragment').sayHello('world');

Custom methods

We can define fragment custom methods by defining them as functions in fragment definition.

These methods are exported to fragment element instance when it is created.

Be carefull about method naming beacause you can accidentally override default fragmentElement methods or other HTMLElement methods.

Fragment element instance reference

To create fragment instance add meta-fragment element to document.

<meta-fragment name="com.example.myFragment"></meta-fragment>

auto

If auto attribute is set then fragment's method resume will be automatically called when fragment is created.

fragmentElement.config

Property config points to fragment definition object.

fragmentElement.model

Object containing fragment's model which is passed to view instance.

fragmentElement.view

Property view points to fragment view instance.

fragment.$

Property $ is bound to fragment view ID's hashmap (viewInstance.$).

fragmentElement.resume(callback)

Resumes fragment - see Fragment lifecycle for more details.

If callback attribute is provided then it will be called when fragment was sucessfuly resumed.

Using callback is recommended because fragment initialization can be asynchonous and thus delayd due to import of modules.

fragmentElement.pause()

Pauses fragment - see Fragment lifecycle for more details.

fragmentElement.render()

Renders fragment view.

fragmentElement.setView(name)

Sets fragment view manually.

fragmentElement.fireEvent(event, data)

Dispatches HTMLElement event specified by eventName and merges data object to Event object.

Fragment events can be bound using standard addEventListener method.

Fragment lifecycle

Fragment's life is divded into created, ready, resumed and paused states.

Created state

Fragment state is set to created when:

  • All modules are imported
  • Fragment model has been initialized
  • onCreate handler has been called
  • In this state view property is not available yet.

Fragment element visibility css property is set to hidden.

Ready state

Fragment state is set to ready when:

  • View has been materialized (but not rendered yet)
  • All child fragments has been created (but not ready and not resumed yet)
  • In this state child fragment properties should be set - provider binding for example.

Resumed state

Fragment state is set to resumed when fragmentElement.resume method has been called.

Resume cycle:

  1. If fragment is resumed at first time then fragment's css property visibility is set to visible.
  2. Resume all child fragments and wait until they all are resumed
  3. Call onResume handler - now view property is available
  4. Call fragmentElement.resume method's callback

In this cycle and in onResume handler we should initialize content providers, bind to their notifications and do other manual binding if neccesary.

If auto attribute has been set to meta-fragment element then fragment will be automatialy resumed right after it's initialization.

Paused state

Fragment state is set to paused when fragmentElement.pause method has been called or when fragment node has been dettached from DOM.

Pause cycle:

  1. Unbind all fragment's view template events
  2. Pause all child fragments
  3. Call onPause handler

In this cycle and in onPause handler we should unbind all events which has been bound to content providers and other stuff. It is because when fragment is not active anymore (maybe beacause of dettaching from DOM) we don't wont to react on changes and update view anymore.

Activity component

Activity extends fragment component. It has same behaviour but is defined in different registry.

Activity definition example

Meta.Activity("com.example.hello", {

    onResume: function(self){
        alert("Hello, Iam activity!");
    }

});

Activity usage example

<meta-activity name="com.example.hello" auto></meta-activity>

Creating activity using JavaScript

Activity component also provides shorthand for creating activity instance programmaticaly.

Meta.CreateActivity(parentElement, "com.example.hello");