Form Worklet

Form worklet is a widget worklet that includes all functionality required to render and process HTML form. Check out class documentation here.

Sample Form

Consider we want to collect feedback from our users regarding the quality of deals which your site offers. Let's create a form for this. It will collect feedbacks and store them in a DB.

1. Create MySQL Table

CREATE TABLE `prefix_Feedback` (
    `id`                bigint unsigned not null auto_increment,
    `name`              varchar(250),
    `email`             varchar(250),
    `rating`            tinyint unsigned,
    `message`           text,
    primary key(`id`)
) engine = MyISAM CHARACTER SET utf8 COLLATE utf8_unicode_ci ;

2. Create Model

File: /protected/models/MFeedback.php

<?php
class MFeedback extends UActiveRecord
{   
    public static function module()
    {
        return 'custom';
    }
 
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }
 
    public function tableName()
    {
        return '{{Feedback}}';
    }
 
    public function relations()
    {
        // no relations so far
    }
 
    public function rules()
    {
        return array(
            array('name,email,rating','required'),
            array('email','email'),
            array('rating','numerical'),
            array('message','safe')
        );
    }
}

UniProgy Framework models are exactly the same as Yii Framework models, so please refer to Active Record and Form Model documentation.

The only difference is that our models should extend from UActiveRecord or UActiveForm and include module() static method (it simply returns model module name).

3. Create Form Worklet

File: /protected/modules/custom/worklets/WCustomFeedback.php

<?php
class WCustomFeedback extends UFormWorklet
{
    public $modelClassName = 'MFeedback';
 
    public function properties()
    {
        return array(
            'elements' => array(
                'name' => array('type' => 'text', 'label' => $this->t('Full Name')),
                'email' => array('type' => 'text', 'label' => $this->t('Email Address')),
                'rating' => array('type' => 'radiolist', 'label' => $this->t('Rate Quality of Our Deals'),
                    'items' => array(
                        0 => $this->t('Low'),
                        1 => $this->t('Medium'),
                        2 => $this->t('High')
                    ), 'layout' => "{label}\n<fieldset>{input}\n{hint}</fieldset>"
                ),
                'message' => array('type' => 'textarea', 'label' => $this->t('Your Personal Feedback'))
            ),
            'buttons' => array(
                'submit' => array('type' => 'submit',
                    'label' => $this->t('Send'))
            ),
            'model' => $this->model
        );
    }
}

At minimum we must define $modelClassName property and provide array of properties - they exactly follow Yii documentation about form builder.

Believe it or not but this is it. That was all we need to do to create a form that would save input to the DB. You can now open http://yourdomain.com/custom/feedback and it will be there.

It automatically does following things:

  1. Renders the form and it automatically becomes an ajax form - submitted data goes to the server via ajax call without page refresh
  2. Receives submit
  3. Shows errors if there are any
  4. Saves data to the DB
  5. Redirects user to home page after success

Modifications

Success URL

We can modify URL where user will be redirected after successful form submission via successUrl() method:

public function successUrl()
{
    return url('/user/login');
}

Success Action

We can even modify the way worklet acts after successful submission. We will utilize ajaxSuccess method for this purpose.

public function ajaxSuccess()
{
    wm()->get('base.init')->addToJson(array(
        'info' => array(
            'replace' => $this->t('Thank you for your feedback!'),
            'fade' => 'target',
            'focus' => true
        ),
        'content' => array(
            'appendReplace' => CHtml::script('$("'.$this->getDOMId().' form").get(0).reset();'),
        ),
    ));
}

In the example above our worklet will return json array that will tell our form to do the following:

  1. Show "Thank you for your feedback!" notice above the form in the worklet notification block (yellow block), focus the screen on that area and slowly fade it away
  2. Append some javascript to the form: that javascript simply finds our form and resets it.

Add Ability to Edit

Let's consider there is already a list of all feedbacks and an "edit" link next to each of them which has the following format: http://yourdomain.com/custom/feedback/id/12 - where id is ID of the associated entry in the DB.

In order to add edit ability to our worklet we need to do a couple of changes:

<?php
class WCustomFeedback extends UFormWorklet
{
    ...
    public $primaryKey = 'id';
 
    public function properties()
    {
        return array(
            ...
            'buttons' => array(
                'submit' => array('type' => 'submit',
                    'label' => $this->isNewRecord?$this->t('Send'):$this->t('Update'))
            ),
            ...
        );
    }
}

In $primaryKey property we must specify what is the name of GET parameter that contains ID of the entry which will be edited. As for label attribute of "submit" button we want to show "Send" if this is a new feedback and "Update" otherwise.