Edit toStructure with a form on the front

Hello,

I would like to create a form which makes it possible to update ToStructure fields (more data) by users on the front end.

I have already managed to do it for simple fields:

But this is more complex.

Is it possible ?

Of course, see example here:

Hello,

Thank you for your reply.

I am testing but it still seems quite complex.

You don’t need the hook, only the addToStructure() method…

Thanks texnixe,

With the help of my brother who is better at PHP we were able to manage the addition (here I had managed myself cool) and modify then delete.

This post was also interesting: Add to structured data remove from structured data from the front end

The question that arises now is what is the best way to manage security because currently we are creating an input field in hidden which displays the line id.

<div class="table-responsive">
    <table class="table table-striped">
        <thead>
            <tr>
                <th scope="col">Date</th>
                <th scope="col">Description</th>
                <th scope="col">Modification</th>
            </tr>
        </thead>
        <tbody id="myTable">
            <?php foreach ($page->listing()->toStructure()->flip() as $listing): ?>
            <tr>

                <td>
                    <?= $listing->date() ?>
                </td>
                <td><?= $listing->description() ?></td>

                <td>
                    <!-- uniquement un user client verra le formulaire -->
                    <?php if (($user = $kirby->user()) && $user->role()->id() === 'client'): ?>

                    <!-- MISE A JOUR (submit_update) -->
                    <form action="" method="post">
                        <div class="form-group">
                            <input type="text" class="form-control" id="date" name="date" placeholder="date" value="<?php echo $listing->date(); ?>">
                        </div>
                        <div class="form-group">
                            <input type="text" class="form-control" id="description" name="description" placeholder="description" value="<?php echo $listing->description(); ?>">
                        </div>
                        <input type="hidden" name="id" value="<?php echo $listing->id(); ?>">
                        <input class="btn btn-primary" type="submit" name="submit_update" value="Mise à jour">
                    </form>

                    <!-- DELETE (submit_delete) -->
                    <form action="" method="post">
                        <input type="hidden" name="id" value="<?php echo $listing->id(); ?>">

                        <input class="btn btn-primary" type="submit" name="submit_delete" value="Supprimer" onclick="return confirm('Êtes vous sur ?')">
                    </form>

                    <?php endif; ?>
                </td>
            </tr>
            <?php endforeach ?>
        </tbody>
    </table>
</div>


<!-- ADD (submit_new) -->
<form action="" method="post">
    <div class="form-group">
        <input type="text" class="form-control" id="date" name="date" placeholder="date" value="">
    </div>
    <div class="form-group">
        <input type="text" class="form-control" id="description" name="description" placeholder="description" value="">
    </div>
    <input class="btn btn-primary" type="submit" name="submit_new" value="Submit changes">
</form>

Our idea would be to check the role “client” of the user + his email to authorize it.

Is it clean?

Because currently all “client” could modify any field, just by modifying the entry.

Here is the code in the controllers:
<?php

// ADD (submit_new)
if(r::is('post') && get('submit_new')) {
    addToStructure(
        page()->uri(), 
        'listing', 
        array("date" => strip_tags(get('date')), 
              "description" => strip_tags(get('description'))
        )
    );
}

// ADD (submit_delete)
if(r::is('post') && get('submit_delete')) {
    $field = 'listing';
    
    $items = page()->{$field}()->yaml();
    unset($items[get('id')]);

    ///dump($items);
    
    $data = yaml::encode($items);
    try {
        page()->update([$field => $data]);
    } catch(Exception $e) {
        echo $e->getMessage();
    }
    // REFRESH PAGE
    echo "<meta http-equiv='refresh' content='0'>";
}

// UPDATE (submit_update)
if(r::is('post') && get('submit_update')) {
    $field = 'listing';
    
    $items = page()->{$field}()->yaml();
    $items[get('id')] = array("date" => strip_tags(get('date')), 
              "description" => strip_tags(get('description')));

    ///dump($items);
    
    $data = yaml::encode($items);
    try {
        page()->update([$field => $data]);
    } catch(Exception $e) {
        echo $e->getMessage();
    }
    // REFRESH PAGE
    echo "<meta http-equiv='refresh' content='0'>";
}

/**
 * Add a new element to a kirby structure field
 * @param string $page
 * @param string $field
 * @param array $data
 */
function addToStructure($page, $field, $data = array()){  
    // REFRESH PAGE
    echo "<meta http-equiv='refresh' content='0'>";

  $fieldData = page($page)->$field()->yaml();
  $fieldData[] = $data;
  $fieldData = yaml::encode($fieldData);
  try {
    page($page)->update(array($field => $fieldData));
    return true;
  } catch(Exception $e) {
    return $e->getMessage();
  }
}

If only a given user should be able to submit this form, then yes, you would have to verify the user.

Also, I don’t quite understand the purpose of the id in the hidden field. All forms should have a CSRF token instead that is than verified in the controller.

Hello,

thank you for your very quick response, we will look.

The id was to determine the row of the table and be able to delete. As it is a structural field it seemed the right solution.

Ah, yes, that makes sense.

Again thank you texnixe for the answer.

I haven’t had much time to continue my development and I haven’t yet implemented csrf ().

I build a cycling site so that members can add information only on the front side. It allows me to learn the roles, the front and I will also immerse myself in languages.

Cookbooks are great on Getkirby but there aren’t that many to do that kind of thing on the front end. An upgrade ?

To share, this is what it can give as a presentation on the front side:

<form action="" method="post">
                                <!-- Button modalUpdate -->
                                <button type="button" class="btn btn-sm btn-primary" data-toggle="modal" data-target="#modalUpdate0">
                                    Modifier la course
                                </button>
                                <input type="hidden" name="id" value="0">

                                <input class="btn btn-sm btn-primary valid" type="submit" name="submit_delete" style="font-family: FontAwesome" value="" onclick="return confirm('Êtes vous sûr de vouloir supprimer la course FSGT 4 et UFOLEP 3 ?')">
                            </form>

I use the id in a hidden field to modify the info:
<input type="hidden" name="id" value="0">

Front side for presentation inspirations: