This forum has moved to a new location and is in read-only mode. Please visit talk.octobercms.com to access the new location.

Incremental
Incremental

Hello, is there a way to reset fields to default values when incorrect ?

DEFAULT_VALUE is not affected in the following code :

public function beforeValidate() {
   if ($this->field == 'Incorrect') {
       $this->field = 'DEFAULT_VALUE';
       throw new \October\Rain\Exception\ValidationException(['field' => 'Invalid Value']);
   }
}

Last updated

mjauvin
mjauvin

Ok, I found how to do it!

In your controller, add this method:

    public function create_onSave()
    {
        $model = $this->formCreateModelObject();
        $model = $this->formExtendModel($model) ?: $model;
        $this->initForm($model);

        $form = $this->formGetWidget();
        $field = $form->getField('name');
        $data = $form->getSaveData();

        if ($data['name'] == 'value') {
            $field->value = 'MyDefaultValue';

            $fieldMarkup = $form->renderField('name', ['useContainer' => true]);

            \Flash::error('My Flash Error');

            return [
                '#' . $field->getId('group') => $fieldMarkup
            ];
        }
        return parent::create_onSave();
    }

Just replace 'name', 'value' & 'MyDefaultValue' with your actual values

This will work for create only, you'll need to do similar things for update in update_onSave()

mjauvin
mjauvin

Nicer versions:

    public function create_onSave($context = null) 
    {    
        $model = $this->formCreateModelObject(); 
        $model = $this->formExtendModel($model) ?: $model;
        $this->initForm($model);

        $fieldName = 'name';
        $defaultValue = 'My Default Value';

        $form = $this->formGetWidget();
        $formData = $form->getSaveData();

        if ($formData[$fieldName] == 'my') {
            $field = $form->getField($fieldName);
            $field->value = $defaultValue;

            $fieldMarkup = $form->renderField($fieldName, ['useContainer' => true]);

            \Flash::error('Invalid Field Value');

            return [
                '#' . $field->getId('group') => $fieldMarkup
            ];
        }
        return parent::create_onSave($context);
    }

    public function update_onSave($recordId = null, $context = null)
    {   
        $model = $this->formFindModelObject($recordId);
        $this->initForm($model);

        $fieldName = 'name';
        $defaultValue = 'My Default Value';

        $form = $this->formGetWidget();
        $formData = $form->getSaveData();

        if ($formData[$fieldName] == 'my') {
            $field = $form->getField($fieldName);
            $field->value = $defaultValue;

            $fieldMarkup = $form->renderField($fieldName, ['useContainer' => true]);

            \Flash::error('Invalid Field Value');

            return [
                '#' . $field->getId('group') => $fieldMarkup
            ];
        }
        return parent::update_onSave($recordId, $context);
    }

Last updated

mjauvin
mjauvin

With less code duplication:

    public function create_onSave($context = null) 
    {   
        $model = $this->formCreateModelObject(); 
        $model = $this->formExtendModel($model) ?: $model; 
        $this->initForm($model); 

        if ($result = $this->formBeforeSave($model)) { 
            return $result; 
        } 
        return parent::create_onSave($context); 
    } 

    public function update_onSave($recordId = null, $context = null) 
    {   
        $model = $this->formFindModelObject($recordId); 
        $this->initForm($model); 

        if ($result = $this->formBeforeSave($model)) { 
            return $result; 
        } 
        return parent::update_onSave($recordId, $context); 
    } 

    public function formBeforeSave($model) 
    {   
        $fieldName = 'name';

        $form = $this->formGetWidget();
        $formData = $form->getSaveData();

        if ($formData[$fieldName] == 'VALUE') {
            $field = $form->getField($fieldName);
            $field->value = $field->getConfig('default'); // use field definition "default" param
            $fieldMarkup = $form->renderField($fieldName, ['useContainer' => true]);

            \Flash::error('Invalid Field Value');

            $result = ['#' . $field->getId('group') => $fieldMarkup];

            return $result;
        }
    }
Incremental
Incremental

Wow ! you're a god !

Thanks, I'm trying to do this at least since "october month" !!!

I thought that with .YAML october was simple to use, but I see now that it's not that simple.

I'm a developper, but can't figure how to find these instructions... I'm gonna try to understand each line...

October really miss simple code SAMPLES, not only a dictionary of functions ;-(

Thanks again for your help !!!

mjauvin
mjauvin

The best way is to browse the source code and understand what's happening and how.

mjauvin
Incremental
Incremental

Thanks again ;-))

Incremental
Incremental

To complete :

Is it right that this code could check complex business validation cases ?

And beforeValidate() check fields values according to YAML and validation rules in the model ?

Incremental
Incremental

Sorry again, I tried your code in my controller in :

/plugins/myname/pluginname/controllers/controllername.php

and nothing is called. Should it really put here ?

mjauvin
mjauvin

yes, it should be in your controller.

mjauvin
mjauvin

Is your controller implementing the FormController behavior?

Incremental
Incremental

My Events.php controller is like this :

<?php namespace LB\Events\Controllers;

use Backend\Classes\Controller;
use BackendMenu;

class Events extends Controller {
public $implement = [
    'Backend\Behaviors\ListController',
    'Backend\Behaviors\FormController',
    'Backend\Behaviors\ReorderController'
];
public $listConfig = 'config_list.yaml';
public $formConfig = 'config_form.yaml';
public $reorderConfig = 'config_reorder.yaml';

public function __construct() {
    parent::__construct();
    BackendMenu::setContext('LB.Events', 'main-menu-item');
}

// Called before the model is validated (CREATE) - Identique à update_onSave()
public function create_onSave($context = null) {  }

// Called before the model is validated (UPDATE) - Identique à create_onSave()
public function update_onSave($recordId = null, $context = null) {   }

public function formBeforeSave($model) {   }
}

Last updated

mjauvin
mjauvin

This should work, I have the exact same code and it works.

Incremental
Incremental

Thanks, I've got it finally working. I won't have done it alone ;-)

Just because I like to understand my code, can you explain the following instruction ?

$result = ['#' . $field->getId('group') => $fieldMarkup];

mjauvin
mjauvin

Incremental said:

Thanks, I've got it finally working. I won't have done it alone ;-)

What was the problem?

Just because I like to understand my code, can you explain the following instruction ?

$result = ['#' . $field->getId('group') => $fieldMarkup];

https://octobercms.com/docs/ajax/update-partials#pushing-updates

$field->getId() returns the id of the HTML element for that field (adding 'group' returns the id of the field group)

mjauvin
mjauvin

Oh, and use "false" in the following line instead of "true" as I posted:

$fieldMarkup = $form->renderField($fieldName, ['useContainer' => true]);
Incremental
Incremental

I wanted to thank you for your precious help. You helped me to find the solution after many months of research. The october learning curve is quite long...

With this method it's possible to modify one field, but what about MORE THAN ONE, for complex business validations ???

mjauvin
mjauvin

Yes, just add more fields in your logic, same method.

Incremental
Incremental

Just to complete, to modify 2 fields :

$result = ['#'.$field->getId('group') => $fieldMarkup, '#'.$field1->getId('group') => $fieldMarkup1];
return $result;

1-20 of 28

You cannot edit posts or make replies: the forum has moved to talk.octobercms.com.