Update field data from frontend with uniform

hi!

i’m pretty new to kirby and especially to php trying to figure out step by step how to change content via forms from the frontend. i got the “creating pages from frontend” tutorial and was wondering how to do similar things, e.g. simply editing field data from a specific page, using the uniform plugin (advantage: clean code and more structure for having more than one form?) and custom actions.

my code:
template:

 <form action="<?php echo $page->url() ?>" method="POST">
             <input name="eingabe1" type="text" value="<?php echo $form->old('ptext') ?>" placeholder="text">
             <?php echo csrf_field() ?>
             <?php echo honeypot_field() ?>
             <input type="submit" value="Submit">
 </form>

controller:
<?php

use Uniform\Form;
     
return function ($site, $pages, $page)
{

    $form = new Form([
        'eingabe1' => []
    ]);
    
    if (r::is('POST')) {
        $form->changeText(['neuertext' => $form]);
    };
    
    return compact('form');
}; 

“changeText action”:

<?php

namespace Uniform\Actions;

use Error;
use Uniform\Form;

class changeText extends Action {
    public function perform() {
        $neuertext = $this->form->data();
        
        try {
            page('testin')->update(['text' => $neuertext]);
        } catch (\Exception $e) {
            $this->fail($e->getMessage());
        }
         
    }
    
}

i think the input is not submitted to $form but to be honest, i don’t really get what is/should happen there. maybe someone could explain how the form input goes into into the $form variable, or maybe i just get the whole thing wrong.

thanks in advance!

dennis

I think you need something similar to the session store example in the doc.

Are you just trying to retain previously entered fields after an error so that the user does not have to fill them in again? Looks like you already have that working and it’s possibly interfering with the text change you are trying to do.

I think this cancelling out what you are trying do with the action.

<?php echo $form->old('ptext') ?>

Users should be able to edit content in fields on the page (so from the frontend)

Most simple example: if there is a page with the field “text”, the field content should be updated from the frontend by typing the new text into a form.

I tried to edit the “email” example from uniform for that.
so there is the form that hands over the typed in data $form(?) to a custom action changeText() which should change the content of the specific field text of the specific page testin to what has been typed into the form.

Kind of abstract still -sorry but generally the idea is to have users upload text and files (images etc) not from the panel but directly via frontend.

I don’t really understand what <?php echo $form->old('ptext') ?> does. but i thought it’s part of the Post/Redirect/Get-Method.

<?php echo $form->old('ptext') ?>

Where did you get that from? You field is called eingabe1 so the key used here should also be eingabe1.

Is the form sent successfully at all?

oh, i think i forgot to change that in the try-and-error process of understanding, sorry.

by clicking on submit the page redirects but nothing happens (no change, no error-message)

From the template:

<input name="eingabe1" type="text" value="<?php echo $form->old('ptext') ?>" placeholder="text">

Looked to me like the value @derp was trying to set was getting over ridden by the old value.

@derp <?php echo $form->old('ptext') ?> if you partially fill in the form and hit submit, this code will put the previously values back in the fields to save the user retyping them, for example if there is a validation error.

The Action must be named differently, ‘Action’ must be part of the class name, at least if you want to call it with a “Magic Method”, see the Uniform documentation on custom action.

Also, $neuertext is an array with all the data from your form fields. Therefore, you have to provide the key for the input field in the update data array, i.e. $neuertext['eingabe1'], so that you only pick the data from that particular field.

Note, you can pass a complete form data array to the update function in case you want to update your page with all fields from the data array

$data = $this->form->data();
page('a-page')->update($data);

However, you should validate user input before storing and escape user input when outputting it.

Here the corrected Action:

<?php

namespace Uniform\Actions;

use Error;
use Uniform\Form;

class ChangeTextAction extends Action {
    public function perform() {
        $neuertext = $this->form->data();
        
        try {
            page('testin')->update(['text' => $neuertext['eingabe1']);
        } catch (\Exception $e) {
            $this->fail($e->getMessage());
        }
         
    }
    
}

You then have to call it in your controller like this:

if (r::is('POST')) {
    $form->changeTextAction();

}

No need to pass any data.

Also, check in your dev tools network tab if the form is sent, i.e. you get a post request.

Edit: I don’t know why, but the form does not send any data from the home page when using an action attribute in Kirby 2.5.8. Works from other pages.

And you don’t need a session storage action, btw., that serves another purpose.

1 Like

thanks a lot!

here is the final code with the option to pass data for further possibilities – maybe somebody can use it.

template:

(...)

<form action="<?php echo $page->url() ?>" method="POST">
            <input name="eingabe1" type="text" value="<?php echo $form->old('eingabe1') ?>" placeholder="text">
            <?php echo csrf_field() ?>
            <?php echo honeypot_field() ?>
            <button class="button" type="submit" name="Submit" value="Register">Register</button>
        </form>
        <?php if ($form->success()): ?>
            Success!
        <?php else: ?>
            <?php snippet('uniform/errors', ['form' => $form]); ?>
        <?php endif; ?>
(...)

controller:

<?php

use Uniform\Form;

return function($site, $pages, $page) {
    
    $form = new Form ([
        'eingabe1' => [
            'rules' => ['required'],
            'message' => ['input required']
        ]
    ]);
    
    if(r::is('POST') && get('Submit')) {
        $data = $form->data();
        $form->ChangeTextAction([
            'page' => $page,
            'field' => 'thefield',
            'fielddata' => $data['eingabe1']
        ]);
    };
    
    return compact('form');
};

action:

<?php

namespace Uniform\Actions;

use Error;
use Uniform\Form;

class ChangeTextAction extends Action {
    public function perform() {
        $params = [
            'p' => $this->option('page'),
            'field' => $this->option('field'),
            'fielddata' => $this->option('fielddata')
        ];
        try {
            $params['p']->update(array(
                $params['field'] => $params['fielddata']
            ));
        } catch (\Exception $e) {
            $this->fail($e->getMessage());
        }
         
    }
    
};
1 Like