Pass data from a form to the data of the $page

Hello,

Just as an exercise, I’m trying to make a WYSIWYG system using Kirby and Vue.js. The front-end edition system works : I can click on a text, it turns into a field containing the text, I clicked on, then I can edit it, click on submit then the field turns into a solid text corresponding to the text written in the field.

I added a final submit button that posts (POST method) all the edited data. I wonder how to pass it to the data of the page. I’m almost ignorant concerning controllers. Here is what I tried :

Template :

<div id="app-wysiwyg">
        <p @click="toggleEdit"> {{ message }} </p>
        <div id="edit">
            <input type="textarea" v-model="message">
            <input type="submit" value="Ok" @click="toggleEdit">
        </div>
        <form action="<?= $page->url() ?>" method="post">
            <input name="message" type="textarea" v-model="message" style="display: none;">
            <input type="submit" value="Valider" @click="toggleEdit">
        </form>
</div> 

Controller :

<?php
return function ($page) {
    $page->message() = $_POST['message'];
    return $page->message();
}; 

Vue :

new Vue({
    el: '#app-wysiwyg',
    data: {
        message: 'Ceci est un paragraphe modifiable, cliquez dessus pour essayer.',
        contentHide: {},
    },
    methods: {
        toggleEdit: function(e) {
            if (e.target.tagName !== 'INPUT') {
                this.contentHide = e.target
                console.log(this.contentHide.tagName)
                let contentWidth = this.contentHide.offsetWidth
                this.contentHide.style.display = "none"
                let edit = document.getElementById('edit')
                edit.style.display = "block"
                edit.firstChild.style.width = contentWidth + "px"
            } else {
                document.getElementById('edit').style.display = "none"
                this.contentHide.style.display = "block"
                this.contentHide = {}
            }
        }    
    }
})

CSS :

#edit {
    display: none;
}

Thanks for your help.

Is the form actually submitted? I only see the toggleEdit action…

And the controller code doesn’t make sense, because you cannot assign anything the a page method. You would have to check for a POST request and then assign $_POST to a variable to further work with it. Please check out the documentation on controllers (you need to return an array).

This part copies the “edit” part in a hidden field that the submit button sends with the POST method.

<form action="<?= $page->url() ?>" method="post">
            <input name="message" type="textarea" v-model="message" style="display: none;">
            <input type="submit" value="Valider" @click="toggleEdit">
        </form>

I’m reading carefully the controllers’ page of the guide.

I read the doc but honestly I have difficulties to understand. Is this better ?

<?php
return function ($page) {
    if($kirby->request()->is('POST') && get('submit') {
        
        $message = $_POST['message'];
        
        return [
            $page->message() => $message
        ];   
    };
};

As I said above, you cannot assign values to page methods.

return [
            'message' => $message ?? ''
        ]; 

Then in your template, you can dump($message).

But check your network tab if the post request is actually sent or if you @click method somehow prevents that.

It looks correctly sent.

The page object is immutable.

What you probably want to do here is update the page using $page->update(). This requires the user to be logged in or using an impersonated user.

I wonder if it wouldn’t make more sense to use the Kirby’s REST API in the Vue context.

If “updating the page” includes to add a new data in the .txt : yes, that’s what I want to do directly in the front-end. The user would be logged in. I you think the Kirby’s REST API is the better tool to do it I’ll check.

Yes, that’s what it means.