Make Your Own Plugin, Part 1: Writing Custom Controls

Once you have used QCubed for a while, you may find you have a need to create your own custom Control, or connect QCubed to an already existing javascript widget.

Start by familiarizing yourself with the various plugins currently written. Take a look at their source code and how the directories are structured. Also take a look at the QCubed core files that are implementations of JQueryUI components, like the Autocomplete component.

There are a many ways to write a custom widget. A couple have already been explained under Creating Your Own Control and Creating a Composite Control. These methods modify currently available QCubed controls. Studying these examples will give you a good understanding of how controls work on the PHP side.

Connecting Javascript Controls to QCubed

There are now many javascript libraries available on the internet that contain a huge variety of javascript controls. These controls can be connected to QCubed so that all the functionality of the control is available to you within PHP. Below is a discussion of some of the aspects of connecting a javascript control to QCubed. For the most part, you can follow the examples of the currently written libraries and JQueryUI components. The basic goal is to maintain sychronization between the javascript control's data, and the data in the PHP control.


First, you must decide on what the base HTML object of the control will be, and this will determine what the base of your Control wil be. For example, if your javascript widget attaches to a <div> block, you should have your control extend from the \QCubed\Control\Panel class, because the \QCubed\Control\Panel outputs a <div>. If you have additional HTML that you need to output, implement a getControlHtml method in your control.

QCubed includes jQuery and uses it for much of its internal function. However, it changes the '$' variable to '$j'. So, to refer to your control for example, you would output the following javascript:


where controlId is the id of your control. You can get your id by accessing the ->ControlId parameter of your control object in PHP.

Make sure you include the javascript for the widget itself by calling addJavascriptFile from your PHP constructor.

Moving Data from PHP to Javascript

How you move data from PHP to Javascript will depend a bit on your javascript widget.

When you want to update your control after initially drawing it, use the addAttributeScript() method. This will execute a javascript function on your control that you would use to do the update. It is also designed so that if the entire control is redrawn, the javascript will not execute, since it will not be needed since the whole control is being drawn. For example, you could do this:

$this->AddAttributeScript('val', $strValue);

to set the value of your control to $strValue on the javascript side. Remember to also save that data into your PHP control, because later your control might completely redraw, and it will need to draw using the new value.

Moving Data from Javascript to PHP

Data comes from the javascript via a variety of mechanisms.

The primary method is via Post variables. All input items, like textboxes and checkboxes are submitted this way. Also select items like lists send there data this way.

To read post variables, create a subclass Control in PHP and override the parsePostData() method. Within that function, examine the $_POST superglobal and update your internal state accordingly.

To have your javascript send POST variables, you can do one of the following:

Another way to push data to PHP is to use the qc.recordControlModification function whenever an aspect of your control changes. Call qc.recordControlModification from your javascript control and pass it your control id, a control property, and a new value for the property. The control property is a property in your PHP control that you can set through the __set magic method. Calling recordControlModification in javascript will cause QCubed to pass that value to your PHP control through that property.

See the \QCubed\Project\Jqui\Accordion control for an example of this method.

Events can also be used to read data from the control during the processing of a specific event as discussed in the jQuery Controls: Adding Actions example.

Many javascript controls these days use ajax or javascript mechanisms to read data in real time. Connecting these controls to QCubed is more complicated, and is dependent on the specific implementation. Here are some examples:

Adding Your Control to the Code Generation Process

If your control is designed to edit a basic type that might come from the database, like an integer, varchar string, or even a list of items that are a result of a primary key relationship, you can add some code to your control to include it in the code generation process to make it easier for other users to bind your control to fields in the database.

If you have based your control on a type that binds to a pre-existing control, you might not need to do anything extra. The \QCubed\Project\Jqui\SelectMenu control is an example of this, which is simply a javascript overlay on a list box.

However, if your interface is a unique way of editing data, you will need to create a new class called ${LIBRARY_CONTROL_CLASS}_CodeGenerator that extends AbstractControl_CodeGenerator (or more likely Control_CodeGenerator) to bind the control to the database. See the Slider_CodeGenerator for an example of how to generate the binding code needed.

Implement the GetModelConnectorParams function to allow a user of the control to set all of your __set parameters through the ModelConnector Designer user-interface. This will make it much easier for users to know and use the capabilities of your control.

Finally, in order to make your control available to the designer as an option for the particular data types your control manipulates, create a file and put it in the /install/project/includes/configuration/control_registry directory. Name it "your_control_name".inc.php.


Read the next chapter to learn about ways to package and distribute your plugin.