HTML Form

The HTML form allows you to efficiently design, validate and populate a HTML form and place it within any template using a single HTML tag. You may create a form by using the create form CLI command, such as:

apex create form <PACKAGE> <ALIAS>

apex create form my-shop product

Using the above example, this will create a new file at `/src/MyShop/Opus/Forms/Product.php, which contains three methods that are explained in the below table.

Method Description
getFields() Defines the form fields contained within the HTML form and their attributes.
getRecord() Retrives a single record from the database to populate the HTML form with.
validate() Provide any necessary additional validation on the HTML form aside from the built-in validation via the field attributes.

There is also one property named $allow_post_values which is a boolean and defines upon populating a form whether or not the system can utilize values from the previously posted form. This is used in case the user needs to be returned to the same form due to validation errors.

GetFields)_

This method is where you define the fields contained within the HTML form and their attributes. You will notice an instance of the FormBuilder class was injected as a property, and this is used to define the form fields.

Looking at the methods available within the FormBuilder class you will see all the various form fields that are available. Each of these methods returns an instance of the FormField class, and by looking through the methods available within the FormField class you will see all attributes available to form fields.

Here's a small example of this method:

public function getFields(array $attr = []): array
{

    // Build form
    $builder = $this->builder;
    $form_fields = [
        'full_name' => $builder->textbox()->placeholder('Full Name')->required(),
        'email' => $builder->textbox()->placeholder('E-Mail Address')->required()->dataType('email'),
        'phone' => $builder->phone(),
        'password' => $builder->textbox()->label('Desired Password')->type('password')->required()->minLength(8),
        'confirm_password' => $builder->textbox()->label('Confirm Password')->type('password')->required()->minLength(8),
        'sep_addl' => $builder->seperator('Additional'),
        'eligible' => $builder->boolean()->label('Are you eligible?')->value('0')->required(),
        'status' => $builder->select()->dataSource('hash.users.status')->required(,
        'submit' => $builder->submit()->value('create')->label('Create Account')
    ];

    // Return
    return $form_fields; 
}

Within the method you simply generate an associative array with each element being a form field. The key is the name of the form field, and the value is an instance of the FormField class. For the value, call the desired form field method from within the $builder / FormBuilder instance, then chain link it as necessary through all desired attributes found within the FormField class

getRecord()

If a record id# is passed when displaying the form, this method will be called to retrive the record from the database providing the values to populate the HTML form with. Return value is an associative array, keys being the names of the form fields, and values being their corresponding value. Below shows an example of this method:

public function getRecord(string $record_id): array
{

    // Get record
    if (!$row = $this->db->getIdRow('products', $record_id)) {
        return [];
    }

        // Return
    return $row;
}

validate() Method

If desired, you may place any additional form validation required aside from the standardized validation added within the attributes of the form fields. See the below section for how to conduct form validation, but an example method is below.

public function validate(array $attr = []): bool
{

    // Check password
    if ($this->app->post('password') != $this->app->post('confirm_password')) {
        $this->view->addCallout("Password do not match", 'error');
        return false;
    }

    return true;
}

Display Forms on Web Pages

You can easily place a HTML form on any view rendered by Apex with a simple HTML tag, for example:

<s:function alias="display-form" form="my-shop.product">

Using the example from the top of this page, this will display the form with the package "my-shop" and alias "product" that is located at /src/MyShop/Opus/Forms/Product.php.

You may also display the HTML form populated with an existing record by adding the "record_id" attribute into the above HTML tag, for example:

<s:function alias="display-form" form="my-shop.product" record_id="51">

This will call the getRecord() method of the form class to retrieve the values to populate the form with. Natrually, you can always use a merge field as the value of the "record_id" attribute for cases when the id# of the record is passed within the query string after clicking a "Manage" button or similar, such as:

<s:function alias="display-form" form="my-shop.product" record_id="~record_id~">

Validate Forms

Aside from manual validation, there are two built-in validation methods both of which are located within the Apex\App\Base\Web\Utils\FormValidator class, and are explained below:

Method Description
validateForm Will validate a HTML form component based on the attributes assigned to the form fields within the getFields() method, and will also execute the validate() method of the class for any custom validation.
validateFields Will validate any HTML form by passing various arrays for required fields, required data types, and min / max lengths.

Below shows an example of both methods:

<?php

use Apex\App\Base\Web\Utils\FormValidator;
use App\MyShop\Models\Product;

/**
 * Product
 */
class Product
{

    #[Inject(FormValidator::class)]
    private FormValidator $validator;

    /**
     * Add product
     */
    public function add(): ?Product
    {

        // Validate form example
        if (!$this->validator->validateForm('my-shop.product')) {
            return null;
        }

        // Example of validate fields
        if (!$this->validator->validateFields(
            'view',
            ['name','amount','category_id','quantity'],
            ['amount' => 'decimal', 'quantity' => 'integer'],
            ['name' => 4]
        ]) {
            return null;
        }
    }
}