1

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

Incremental
  • 27
  • 1
  • 8
  • Did you try the `filterfields` method? You can manipulate backend fields value. See here : https://octobercms.com/docs/backend/forms#filter-form-fields – Raja Khoury Nov 09 '19 at 13:36
  • Thanks, I tried this function, but : 1) I'm unable to compare a text field with a value ie : if ( $this->nom == "toto" ) {} 2) I don't know how to modify a form field value, depending on my validation logic ? – Incremental Nov 10 '19 at 16:13
  • I added a small example below. – Raja Khoury Nov 10 '19 at 18:29

2 Answers2

0

This can all be done in the models.php file and working with Model Events. You can call the specific model facades that you want to register as well at the top with use Author\Plugin\Models\Model .

For example I like to append the slug with the ID so you can use the afterSave() event. You use the record with $this.

public function afterSave()
{
    $id = $this->id;
    if (strpos($this->slug, '-'.$id) === false) 
    {
        $this->slug = $this->slug.'-'.$id;
    }
}

If you want to validate the model you can use the public $rules found here. Here is an example of what a required unique name would look like and an image of what pops up when the validator is fails.

public $rules = [
    'name' => 'required|unique:author_plugin_database',
];

enter image description here

Pettis Brandon
  • 875
  • 1
  • 6
  • 8
  • Thanks Brandon for your kind answer ! I tried afterSave() but as I have many fields in my form, I haven't set all and only setFieldsAttribute() and beforeValidate() are called. In those methods I can only get form values and I'm unable to set them programatically. What is the correct syntax to change a form field value ? – Incremental Nov 10 '19 at 15:05
  • Sorry I misunderstood what you were trying to do. Raja has a closer answer to what you are trying to do than me. – Pettis Brandon Nov 11 '19 at 18:03
  • Thanks Brandon. I note your answer for other purposes. filterFields() is now invoked in my form, but I can't modify form values before submission -> cf. picture – Incremental Nov 11 '19 at 18:26
0

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';
    }
}
Raja Khoury
  • 3,015
  • 1
  • 20
  • 19
  • 1
    Oh my God ! Thanks Raja. I spent 2 weeks on that problem !!! The echo() was intended to debug. I didn't think it could disturb the validation. Now it's working ! Thanks again !!! Do you have an idea on how I could have popups for debug ? – Incremental Nov 12 '19 at 19:27
  • I also found `\Flash::info('Hello');` for a kind of popup. Many thanks Raja ! – Incremental Nov 12 '19 at 21:48