Search code examples
octobercmsoctobercms-backend

Octobercms Builder - How to write validation code for backend form and modify fields


I am new to this fantastic October after 10 years of Joomla and would like to continue on it. I'm using the great Builder plugin and would like to have 'complex' validations in back-end with 'create' or 'update' forms.

After many time browsing the net, I can't figure how to and where to put code to add business validation rules ?

I played with yaml options to have dynamic fields and simple validations. Now I would like to have complex rules, like : if a category is X and a type is Y then the (text) name field is SET to 'ZZZ' Could somebody put me on the way to add such code in PHP ?

I'm able to read field values, but I can't change the inputs programmatically. After many tries, I'm stuck on the problem. Any help would be greatly appreciated. Thanks.

[EDIT] After Raja help, I modified my code like this : PHP Model

class Event extends Model {
    use \October\Rain\Database\Traits\Validation;
    use \October\Rain\Database\Traits\SoftDelete;

    public $rules = [];

    // in models/your_object_model
    public function filterFields($fields, $context = null) {
        echo "\r\n".'filterFields() : '.$this->nom."\r\n";
        // var_dump($fields->nom);
        if ( $this->nom == 'toto' ) {
            echo $this->nom.' is french'."\r\n";
            $fields->pays->value = 'FR';
            $fields->pays->hidden = true;
            $fields->ville->value = 'Paris';
        }
    }
}

YAML :

fields:
    nom:
        label: Nom
        span: full
        type: text
    description:
        label: Description
        size: ''
        span: full
        type: richeditor
    pays:
        label: Pays
        span: auto
        default: US
        type: text
        dependsOn: nom
    ville:
        label: Ville
        span: auto
        default: NY
        dependsOn: nom
        type: text

What I understood is that filterFields() is fired based on the YAML dependsOn: nom.

When I fill 'Nom' and click in Description, the result is now :

1) I'm still unable to change a value in the form as I go in the function, because I display the string "toto is french"

2) On the text fields I try to modify, I get and endless spinner and the fields now can't be entered with mouse, only with keyboard

3) How could I remove the green string X_OCTOBER_ASSETS ?

Picture of the result on Description clic


Solution

  • To manipulate form fields you should override the filterFields method in your model - Docs.

    Assume our model has 4 fields where Name and Publish depend on the values of Category and Type.

    Fields Definition

    category:
        label: Category
        type: dropdown
        options:
            category_a: Category A
            category_b: Category B
            category_c: Category C
    type:
        label: Type
        type: dropdown
        options:
            type_a: Type A
            type_b: Type B
            type_c: Type C
    name:
        label: Name
        comment: 'Comment..'
        dependsOn: [category,type] 
    
    publish:
        label: Publish
        type: switch
        comment: 'Comment..'
        default: true
        dependsOn: [category,type]
    

    Note: Set the field dependencies using the dependsOn option. Here the Name field depends on category and type.

    Model

    public function filterFields($fields, $context = null)
    {
        // Category selected has a value of 'category_b';
        if ($this->category == 'category_b') {
    
           // Try this to see available properties on this field type
           // var_dump($fields->name);
    
            // Category = 'category_b' && Type selected = 'type_c'...
            if ($this->type == 'type_c') {
                $fields->name->value = 'Category set to B and Type to C';
                $fields->publish->value = false;
                $fields->publish->hidden = true;
            } else {
                $fields->name->value = "Category set to B";
                $fields->name->comment = 'Comment changed..';
                $fields->publish->value = false;
                $fields->publish->comment = "Switch has been turned off";
            }
        }
        elseif (($this->category == 'category_a') && ($this->type == 'type_a')) {
            $fields->name->value = 'Category set to A';
            // ect...
        }
    }
    

    This is very straight forward. You can update all properties of a certain field which is very helpful if you just need to display a comment or hide something. The context argument gives you more control when to apply the filters e.g update

    Hope this will help you get started.

    EDIT

    Why would you want to add echo $this->nom.' is french'."\r\n"; and echo "\r\n".'filterFields() : '.$this->nom."\r\n"; to your filterFields function?

    Just remove these lines and you won't have any errors.

    In my example i mentioned this as a quick way to visualize data response.Take a look at the Backend\Classes\Form and Backend\Classes\FormField to better understand how it works.

    Your method may look like this :

    public function filterFields($fields, $context = null) {
        if ( $this->nom == 'toto' ) {
            $fields->pays->value = 'FR';
            $fields->pays->hidden = true;
            $fields->ville->value = 'Paris';
        }
    }