Documentation‎ > ‎

QxTransformer Component Model

For any real application, it is impossible to put all the code into one file. The best way in such situation is to split your application to logically pieces and integrate them. This will make the application much easier to maintain and will also increase flexibility. Plus, it will result in a much cleaner architecture and design of the application. This principle applies to user interface building.


This document describes the QxTransformer "Component Model" which is intended to make your application more modular and flexible.

What is a component?

Components are logically complete and/or reusable parts of the application’s UI. For example, think of a window with all its content, a panel with some elements, or an informational block which can be used in different places in your application.


Example: You have big application and users have the possibility to send feedback from a few places in your app. Instead of duplicating this form in all these places you can write only one component with business logic which sends data to server and use this for each place where you would like to include this form.


QxTransformer Component Model is similar to Flex’s Code Behind approach. The general way to create a component is:


1) Write XML UI for your component

2) Write a class with event handlers or specific functions (if needed)

3) Add newly created component in a file where you want to use it.


Quite simple... Let’s look into each of these steps in more detail.

Writing XML UI for your component

The XML file containing a component has its own specific root tag  qxt:component (in contrast to qx:application for a regular application). It tells the toolkit that you’re defining a component here and it should be processed as such.


Example: Imagine, just for the purpose of an example, that you have 3 tabs with identical feedback forms. Feedback form has 2 fields - Name and Message.


The way how to do this without components is to duplicate this structure 3 time.  Not a good idea, since if you want to change something (e.g. add Company Name field to the form) eventually, you will have to change it in three places in your code.


Let’s create component for this form and will use it in any place where we would like to integrate it.


feedback/FeedbackFrom.xml


<?xml version="1.0" encoding="UTF-8" ?>

<qxt:component

    xmlns:qx="http://www.qxtransformer.org/qooxdoo/0.8"

    xmlns:qxt="http://www.qxtransformer.org/extension/0.4"

    className="feedback.FeedbackForm"

    author="Siarhei Barysiuk">

<qx:groupBox legend="Feedback form">

    <qx:vbox>

        <qx:composite padding="5">

          <qx:hbox spacing="5">

              <qx:label content="Name" width="70"/>

              <qx:textField value="Enter your name" width="200"/>

          </qx:hbox>

        </qx:composite>

        <qx:composite padding="5">

          <qx:hbox spacing="5">

              <qx:label content="Message" width="70"/>

              <qx:textarea value="Enter your message" width="200"/>

          </qx:hbox>

        </qx:composite>

        <qx:button label="Send" allowGrowX="false"/>

    </qx:vbox>

</qx:groupBox>

</qxt:component>



We define qxt:component with the class name feedback.FeedbackForm (qxtransformer will generate JavaScript class with such name). qxt:component has only one child (only one child is allowed)  - qx:groupBox which creates group box and defines how to FeedbackForm should behave. It allows qxtransformer to understand how to process custom component, because it know how to process groupBox, e.g. add to parent, but knows nothing about FeedbackForm. qx:groupBox is some kind of behavior-element. Group box contains form fields.


Now if you run ./generate.py transform, you will get new class feedback.FeedbackForm in classes folder next to the xml file.


Writing a code behind class

Now we need to write processing code for created form. We could place the code right in XML file, but generally, this is not a good idea, because you mix presentation and logic, and your code quickly become unmaintanable. Let’s create code behind for this component. This is a class which extends behavior-element class and contains some custom logic.


qx.Class.define("feedback.FeedbackFormClass",

{

      extend : qx.ui.groupbox.GroupBox,

      construct: function() {

          this.base(arguments);

      },

      members: {

...

          

      }

});


And add extend="feedback.FeedbackFormClass" to qxt:component. Now our comopnent extends feedback.FeedbackFormClass and feedback.FeedbackFormClass, in turn, extends qx.ui.groupbox.GroupBox.


On the next step we need to add processing code to FeedbackFormClass


      members: {

          processForm: function() {

              alert('processForm');

          }

      }


and link function processForm with ‘Send’ button.


<qx:button label="Send" allowGrowX="false">

<qxt:listener type="execute" self="this" delegate="processForm"/>

</qx:button>


But our processForm function is just test sample. In real application we need to get all data from the form and send it to server (we leave out the transport code in this sample). How to get information from the form’s fields? If we don’t define any scope attributes for widgets they will be generated as local variables (take a look at generated code if you’re curious). But you’re able to control this  behavior and add them to class instance.


<qx:textField id="name" qxt:scope="this" value="Enter your name" width="200"/>


There are 2 additional attributes: id and qxt:scope. Id attribute defines a name of this filed. qxt:scope defines scope for this variable (see documentation for all available values). The generated code will look like:


var name = new qx.ui.form.TextField("Enter your name");

this.name = name;


So, you are able to get information from your code behind.

 

processForm: function() {

var name = this.name.getValue();

var message = this.message.getValue();

              

//transport code goes here....

}


We have finished our component and now we need to use it in our application.


Using components in application


We have simple application with tab view and  3 pages in it.


<qx:application

    xmlns:qx="http://www.qxtransformer.org/qooxdoo/0.8"

    xmlns:qxt="http://www.qxtransformer.org/extension/0.4"

    className="feedback.Application"

    author="Siarhei Barysiuk">

  

<qx:tabView width="500">

        <qx:page label="Feedback Page 1">

            <qx:vbox>

                <!-- feedback form here -->

            </qx:vbox>

        </qx:page>

        <qx:page label="Feedback Page 2">

            <qx:vbox>

                <!-- feedback form here -->

            </qx:vbox>

        </qx:page>

        <qx:page label="Feedback Page 3">

            <qx:vbox>

                <!-- feedback form here -->

            </qx:vbox>

        </qx:page>

    </qx:tabView>

</qx:application>


Firstly we need to give a hint to qxtransformer where to find our component. We will do this with help of XML namespaces. Just add to qx:application


xmlns:fb="feedback.*"


This line gives an information where to find defined components. In this case it is class/feedback/*. QxTransformer will analyze this folder - class package - (only this but not child folders), will get information about all components (in our case  only FeedbackForm) and will store this information for further operations. The toolkit will do it automatically for you. Now you can use feedback form in the application:


<fb:FeedbackForm/>


The final application


<?xml version="1.0" encoding="UTF-8" ?>

<qx:application

    xmlns:qx="http://www.qxtransformer.org/qooxdoo/0.8"

    xmlns:qxt="http://www.qxtransformer.org/extension/0.4"

    xmlns:fb="feedback.*"

    className="feedback.Application"

    author="Siarhei Barysiuk">

<qx:tabView width="500">

        <qx:page label="Feedback Page 1">

            <qx:vbox>

                <fb:FeedbackForm/>

            </qx:vbox>

        </qx:page>

        <qx:page label="Feedback Page 2">

            <qx:vbox>

                <fb:FeedbackForm/>

            </qx:vbox>

        </qx:page>

        <qx:page label="Feedback Page 3">

            <qx:vbox>

                <fb:FeedbackForm/>

            </qx:vbox>

        </qx:page>

    </qx:tabView>

</qx:application>


That's it. With this simple pattern, you can completely modularize your UI code.