<p>There are several things you may need to dig into more to get the full picture here but here's a general idea of how you can approach this in Craft 3.</p>

<p>Flash errors are useful to display a message in the Control Panel, but you'll need to prepare a model with errors and signal to the controller that the form submission has failed to return errors to your template. Also, it's not necessary to use the <code>redirect</code> method in this situation as the Controller request can return your errors to the template simply by preparing them using <code>setRouteParams</code> and returning <code>null</code>.</p>

<p>A common pattern that Craft and several plugins use to do this is as follows. The method below would be the method in your controller that receives the form submission:</p>

<pre><code>public function actionMyControllerAction()
{
    $this-&gt;requirePostRequest();

    // Build a model of the data you are submitting
    $model = new MyModel();
    $model-&gt;someOptionalAttribute = Craft::$app-&gt;getRequest()-&gt;getBodyParam('someOptionalAttribute');

    // The `getRequiredBodyParam` method can help validate required fields
    $model-&gt;someRequiredAttribute = Craft::$app-&gt;getRequest()-&gt;getRequiredBodyParam('someRequiredAttribute');

    // After you prepare the model, hand things off to a service 
    // to validate and/or save things to the database
    // The "saveThisModel" method can run any additional 
    // validation you need to run, add errors to the model,
    // and return `false` if validation fails 
    if (!Plugin::getInstance()-&gt;myService-&gt;saveThisModel($model)) {

        Craft::$app-&gt;getSession()-&gt;setError(Craft::t('my-plugin', 'Unable to save item.'));

        // This is where you name the thing you are returning to your template with errors.
        // In this example, the 'myModel' variable would be available to your submitted template
        Craft::$app-&gt;getUrlManager()-&gt;setRouteParams([
            'myModel' =&gt; $model
        ]);

        return null;
    }

    Craft::$app-&gt;getSession()-&gt;setNotice(Craft::t('my-plugin', 'Item saved.'));

    // Redirects to wherever the submitted 'redirect' input points to
    return $this-&gt;redirectToPostedUrl();
}
</code></pre>

<p>If validation fails, in your template, the <code>myModel</code> variable will be available and you can access all errors as an array, or an array of errors for an individual field. You'll need to loop through this in your template. For simplicity here, I'm just dumping them:</p>

<p>All Errors:</p>

<pre><code>{{ dump(myModel.getErrors()) }}
</code></pre>

<p>Errors for a specific field:</p>

<pre><code>{{ dump(myModel.getError('someOptionalAttribute')) }}
</code></pre>

<p>You may also have to add some conditional logic around checking if the <code>myModel</code> variable exists or has errors. You can use Craft's form macros in your template to help with this. Search the Craft codebase templates folder for <code>forms.</code> and you'll find several examples. Here's a simplified Text Field macro that would display an error for the Categories <code>title</code> field.</p>

<pre><code>{% import "_includes/forms" as forms %}

{{ forms.textField({
    label: "Title"|t('app'),
    siteId: category.siteId,
    id: 'title',
    name: 'title',
    value: category.title,
    errors: category.getErrors('title'),
    required: true,
    maxlength: 255
}) }}
</code></pre>

<p>In this case, the Craft Categories controller the <code>actionSaveCategory</code> is returning the <code>category</code> variable to the template using the same pattern that is described above:</p>

<pre><code>if (!Craft::$app-&gt;getElements()-&gt;saveElement($category)) {

    // ...

    Craft::$app-&gt;getSession()-&gt;setError(Craft::t('app', 'Couldn’t save category.'));

    // Send the category back to the template
    Craft::$app-&gt;getUrlManager()-&gt;setRouteParams([
        'category' =&gt; $category
    ]);

    return null;
}
</code></pre>

CC BY-SA 4.0
2019-05-26T21:43:36.727Z
Awesome answer thanks! quick question, how do you access the `forms` macro? I tried using this but it says that it's unknown.
Lea Hayes
CC BY-SA 4.0
2019-05-28T11:35:27.857Z
You'll need to import Craft's form macro file at the top of your template `{% import "_includes/forms" as forms %}`. You can find lots of examples of this if you take a look through the `vendor/craftcms/cms/templates` folder. I've updated the example with the macro to include this line in the answer above.
Ben Parizek
CC BY-SA 4.0
2021-12-09T17:02:36.887Z
You also need to grab the model on your edit route, using  `Craft::$app->urlManager->getRouteParams()` and getting the `category` key, which will contain the model from the save action
Matanya
CC BY-SA 4.0
2019-05-26T14:51:51.193Z
2019-05-28T11:36:01.743Z
2019-05-28T11:36:01.743Z
Ben Parizek
<p>I have a form in a template which makes a request to the specified action (a controller).</p>

<p>The controller decides that there is an issue with the inputs and needs to provide error output for the user. To do this I am using the flash error feature of Craft.</p>

<p>However, I'm unsure how to re-populate the form with the old values when it is next shown.</p>

<p>At the moment I am redirecting to the form page again using <code>$this-&gt;redirect</code> but the user inputs get erased each time.</p>

<templating><form><controller>
How to re-populate form with old values when submitted from a controller?
# How to re-populate form with old values when submitted from a controller?

(Asked by: username_0 on 2019-05-26)

I have a form in a template which makes a request to the specified action (a controller).

The controller decides that there is an issue with the inputs and needs to provide error output for the user. To do this I am using the flash error feature of Craft.

However, I'm unsure how to re-populate the form with the old values when it is next shown.

At the moment I am redirecting to the form page again using `$this->redirect` but the user inputs get erased each time.

**Tags:** templating, form, controller

---

## 1 answers

### Answer by username_1 on 2019-05-26. Score: 4 | Accepted answer

There are several things you may need to dig into more to get the full picture here but here's a general idea of how you can approach this in Craft 3.
Flash errors are useful to display a message in the Control Panel, but you'll need to prepare a model with errors and signal to the controller that the form submission has failed to return errors to your template. Also, it's not necessary to use the redirect method in this situation as the Controller request can return your errors to the template simply by preparing them using setRouteParams and returning null.
A common pattern that Craft and several plugins use to do this is as follows. The method below would be the method in your controller that receives the form submission:
public function actionMyControllerAction()
{
    $this->requirePostRequest();

    // Build a model of the data you are submitting
    $model = new MyModel();
    $model->someOptionalAttribute = Craft::$app->getRequest()->getBodyParam('someOptionalAttribute');

    // The `getRequiredBodyParam` method can help validate required fields
    $model->someRequiredAttribute = Craft::$app->getRequest()->getRequiredBodyParam('someRequiredAttribute');

    // After you prepare the model, hand things off to a service 
    // to validate and/or save things to the database
    // The "saveThisModel" method can run any additional 
    // validation you need to run, add errors to the model,
    // and return `false` if validation fails 
    if (!Plugin::getInstance()->myService->saveThisModel($model)) {

        Craft::$app->getSession()->setError(Craft::t('my-plugin', 'Unable to save item.'));

        // This is where you name the thing you are returning to your template with errors.
        // In this example, the 'myModel' variable would be available to your submitted template
        Craft::$app->getUrlManager()->setRouteParams([
            'myModel' => $model
        ]);

        return null;
    }

    Craft::$app->getSession()->setNotice(Craft::t('my-plugin', 'Item saved.'));

    // Redirects to wherever the submitted 'redirect' input points to
    return $this->redirectToPostedUrl();
}

If validation fails, in your template, the myModel variable will be available and you can access all errors as an array, or an array of errors for an individual field. You'll need to loop through this in your template. For simplicity here, I'm just dumping them:
All Errors:
{{ dump(myModel.getErrors()) }}

Errors for a specific field:
{{ dump(myModel.getError('someOptionalAttribute')) }}

You may also have to add some conditional logic around checking if the myModel variable exists or has errors. You can use Craft's form macros in your template to help with this. Search the Craft codebase templates folder for forms. and you'll find several examples. Here's a simplified Text Field macro that would display an error for the Categories title field.
{% import "_includes/forms" as forms %}

{{ forms.textField({
    label: "Title"|t('app'),
    siteId: category.siteId,
    id: 'title',
    name: 'title',
    value: category.title,
    errors: category.getErrors('title'),
    required: true,
    maxlength: 255
}) }}

In this case, the Craft Categories controller the actionSaveCategory is returning the category variable to the template using the same pattern that is described above:
if (!Craft::$app->getElements()->saveElement($category)) {

    // ...

    Craft::$app->getSession()->setError(Craft::t('app', 'Couldn’t save category.'));

    // Send the category back to the template
    Craft::$app->getUrlManager()->setRouteParams([
        'category' => $category
    ]);

    return null;
}

> **Comments:**
> **username_0**: Awesome answer thanks! quick question, how do you access the `forms` macro? I tried using this but it says that it's unknown.  
> **username_1**: You'll need to import Craft's form macro file at the top of your template `{% import "_includes/forms" as forms %}`. You can find lots of examples of this if you take a look through the `vendor/craftcms/cms/templates` folder. I've updated the example with the macro to include this line in the answer above.  
> **username_2**: You also need to grab the model on your edit route, using  `Craft::$app->urlManager->getRouteParams()` and getting the `category` key, which will contain the model from the save action  

---

