Documentation

1 Getting Started
2 Design Overview
3 Page Controller Boot Process
4 Your First App
5 Page Controller
6 Modules
7 Components
8 jqcEmpty
9 jqcLabel
10 jqcButton
11 jqcLayer
12 jqcPanelDeck
13 jqcAccordion
14 jqcProgressBar
15 Data Binding & Remote Data Synchronization
16 jqcDataService
17 jqcDataModel
18 jqcViewModel
19 jqcList
20 jqcTable
21 jqcForm
22 jqcResponsiveLayoutManager
23 jqcTreeList
24 Demos

Components


This document matches version 1.6.0 .

Components are reusable pieces of code. Components typically has application independent functionality, but components can also be used for application specific functionality in the situations where that makes sense. For instance, a remote data service could be implemented as a component instead of included as part of a module.

Components can be both visual (like GUI components normally are), or non-visual (like a remote data service or a timer component). There are no strict rules for what can and cannot be in a component, but as mentioned earlier their intention is to contain reusable code - either across applications, or within the same application. Additionally, jqComponents has a built-in set of components which you can reuse across your applications so you don't have to code everything yourself.

Adding Components to the Page Controller

Adding components to the page controller is covered detail in the text about the page controller. This text will briefly repeat the basics though.

You add components to the page controller by inserting the jqc-type attribute into the HTML element you want the component to be associated with. Here is an example:

<span id="theLabel" jqc-type="jqcLabel"></span>

The page controller will scan the page for HTML elements with the jqc-type attribute during its boot process, and instantiate the corresponding components and attach the HTML elements to the components.

Creating Custom Components

As mentioned earlier, jqComponents has its own set of built-in components you can use. If you cannot find a component that fits your needs, you can implement a component yourself.

If you want the page controller to be able to instantiate the component for you, you need to register a component factory for your custom component type. The component type is what is specified inside the jqc-type attribute in the HTML elements that have components associated with them.

From version 1.4.0 you can use a span element with the attribute jqc-factory to declare a component factory. Here is an example:

<span jqc-factory="xyzImageSlider"></span>

<script>

function xyzImageSlider() {

    var component = {};

    component.render = function() {
        //render the image slider
    }

    return component;
}
</script>

The page controller will scan the page for HTML elements with a jqc-factory attribute when it boots, and registers the declared component factories.

Once a factory function for a component type is registered you can refer to that type inside the jqc-type attribute of an HTML element, just like with the built-in components. Here is an example that refers to the xyzImageSlider above:

<div jqc-type="xyzImageSlider"></div>

You can also add the component factory inside the postRegister() function of a module. The postRegister() function on modules are called right after the page controller is done registering its own built-in factories, and before any components are yet instantiated. Here is how you would plug the above component factory into the page controller from the postRegister() function of a module:


<span jqc-module="myModule" ></span>

<script>
    function myModule() {
        var module = {};

        module.postRegister = function() {
            module.jqc.pageController.addFactory("xyzImageSlider",
                function() {  return xyzImageSlider(); }
            );
        }

        return module;
    }
</script>

<script>
    function xyzImageSlider() {

        var component = {};

        component.render = function() {
            //render the image slider
        }

        return component;
    }

</script>

Actually, this statement:

module.jqc.pageController.addFactory("xyzImageSlider",
    function() {  return xyzImageSlider(); }
);

Could be reduced a bit to this:

module.jqc.pageController.addFactory("xyzImageSlider", xyzImageSlider );

However, if for some reason the xyzImageSlider function is not present in the HTML page, the second version will make your code fail when the browser tries to interpret it, whereas the first version only fails if the page controller actually tries to create an xyzImageSlider component (if it invokes the factory function).

Component Functions

For a component to be managed by the page controller it can implement one or more of the following functions:

Function NameDescription
configure() Called by the page controller once all components found in the HTML page are instantiated.
layout() Called by the page controller once all components have been configured. This typically only activates the responsive layout manager, if you are using that.
render() Called by the page controller once all components are ready to be rendered (after layout). You can also call this function yourself later, if you need to re-render a component.

configure()

Inside your component's configure() function it can configure itself. It can do so by looking at the HTML element it is associated with. The component has access to the associated HTML element via its jqc object, which is set on the component by the page controller. Here is an example:

function xyzImageSlider() {

    var component = {};

    component.configure = function() {
        component.repeatCount =
        component.jqc.element.attr("xyz-repeat-count");
        }

    component.render = function() {
        //render the image slider
    }

    return component;
}

In this example the component accesses its associated element and looks for a xyz-repeat-count attribute. The example doesn't actually do anything interesting with the attribute value, but a full implementation might.

You could also iterate through any child elements of the associated HTML element. These child elements could be used as a template for how the component is to render itself (for components where that would make sense), or they could contain more advanced configuration. After reading the configuration your component could remove these child elements, if you don't want them to be part of the DOM after configuration. Remember, the jqc.element is a jQuery wrapped DOM element, so you can do anything with it that you can normally do in jQuery.

layout()

The layout() function is called after all components have had their configure functions called. The purpose of the layout() phase is to give components a chance to do some dimension calculations before its render() function is called.

Actually, the primary use of the layout() function is to enable the jqcResponsiveManager to layout the HTML elements before any of the components have their render() functions called. This is done to insure that HTML elements have correct dimensions before the components start rendering themselves. Thus, the jqcResponsiveLayoutManager contains a layout() phase, but your components don't have to.

render()

Inside the component's render() function the component can render itself. This is often done by generating HTML and inserting that HTML into the component's associated HTML element. Here is an example:

function xyzImageSlider() {

    var component = {};

    component.render = function() {
          component.jqc.element.html("<img src='...'>");
    }

    return component;
}

Remember, the jqc.element object is a jQuery wrapped DOM element, so you can use the html() and text() on it, just as if you had selected the HTML element using jQuery.

You do not necessarily have to re-generate the child HTML elements of the associated HTML elements for every call to render(). You might just create the child HTML elements once, and then just update their CSS class subsequently, or whatever else you might need.

You can also call API functions on an HTML5 canvas inside the render() function, if you need to render your component using an HTML5 canvas.

If a component has had its internal state altered it may need to re-render itself. This can be done by calling render() again. You can also have internal sub-rendering methods which only update part of the component's HTML when only part of its internal state has been changed. How you re-render a component is up to you. The page controller only calls render() once - during its boot phase. After that render() is only called if you explicitly call it.

Note: Some built-in components re-render themselves automatically when you change their internal state. For instance, all components using a ViewModel internally will automatically re-render themselves when the ViewModel is changed. This re-rendering is not managed by page controller, but by the ViewModel and the components.