Inertia data not updated on form submission

I have a page with a form, but also some other data outside of this form that needs to be updated once the form submits. The problem is that Inertia.js is not picking up data automatically on form submission. I tried lots of things like setting preserveState to false, but then validation errors do not appear. The problem is that the data is not updated automatically, but only when I reload the page.

What am I doing wrong?

shogun
shogun
0
27
1948
alex
alex
Moderator

Did you mean you have a form, and then data outside of the form on the page that needs to be shown once the form is submitted?

e.g. I submit a form to update my profile and then I need other data to be refreshed at the same time.

If you could post some small code examples to demonstrate that would be super helpful :)

shogun
shogun

Exactly like this. But, of course once i refresh the page, the data is picked up from backend and it works. In laravel after form submission i just redirect back and this is it.

No matter what I do after form submission in vue the page will not update, it is like it preserves the state.

Like I said, i tried lots of things and preserveState: false solves the thing, but then validation errors disappear once i click on the submit button.

const submit = () => { form.post(submitRoute, { onFinish: () => form.reset(), }); };

shogun
shogun

My form is defined like this:

const form = useForm(props.productsPricingSalesNetwork)

Technically this data is coming from backend and then i loop through this in a table. The reason that I'm doing this is that i do not want to have create and edit form, but only a single form that will work for both create and edit. Maybe this is causing a problem...

alex
alex
Moderator

Thanks for extra information. Can I see how you're passing the data down from your controller to the component?

shogun
shogun

This is the code in laravel controller:

return inertia()->render('MarketingMix/Network/Create', [
    'company' => CompanyResource::make($company),
    'product' => ProductNetworkResource::make($product),
    'productsPricingSalesNetwork' => NetworkResource::make($product),
    'customerTypes' => CustomerTypeResource::collection($customerTypes),
    'reservedNetworkManagements' => $reservedNetworkManagements,
]);

then in vue

const props = defineProps({
    company: Object,
    product: Object,
    salesNetwork: Object,
    productsPricingSalesNetwork: Object,
    customerTypes: Object,
    reservedNetworkManagements: Object,
})
whoami (Daryl)
whoami (Daryl)

@Shogun to make the code readable, you can wrap it using backticks.

E.g.

```

// your code

```

alex
alex
Moderator

Thanks @whoami. I have fixed this for Shogun.

alex
alex
Moderator

I think the problem you're having is doing form.reset(). This is going to set the form back to the original values set once the form has been submitted (the old data).

Can you try removing form.reset() and see what happens?

shogun
shogun

@alex This does not solve the issue.

Technically i want to do the same thing as here on this forum. When you click save page is automatically taking the latest data and immediately showing my post. The thing is that my data is just not refreshing.

As I said, the only thing that managed to solve my problem is preserveState: false, but then validation errors do not appear.

Haz
Haz
Moderator
const submit = () => { form.post(submitRoute, { onFinish: () => form.reset(), }); };

What is submitRoute? What response is it returning? It's a bit difficult to help without seeing the bigger picture.

shogun
shogun

This is the script setup part

const props = defineProps({
        company: Object,
        product: Object,
        salesNetwork: Object,
        productsPricingSalesNetwork: Object,
        customerTypes: Object,
        reservedNetworkManagements: Object,
        canViewEconomicsReport: Boolean,
    })

    const product = props.product

    const form = useForm(props.productsPricingSalesNetwork)

    const submitRoute = route('network.save', product)

    const submit = () => {
        form.post(submitRoute, {
            preserveState: false,
            onFinish: () => form.reset(),
        })
    }

this is the template

<form @submit.prevent="submit" class="page-text-xs">
                <table class="table table-xs table-centered">
                    <thead>
                        <tr>
                            <th>{{ __('customer') }}</th>
                            <th>{{ __('minimum_order') }}</th>
                            <th>{{ __('discount') }}</th>
                            <th>{{ __('network_management') }} %</th>
                            <th colspan="4" class="text-center">{{ __('partition_of_rnm') }}</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr v-for="(ppsn, index) in form.customer_types">
                            <td>
                                <TextInput 
                                    v-model="ppsn.network_management" 
                                    :error="form.errors[`customer_types.${index}.network_management`]" 
                                    inputType="hidden"
                                />
                            </td>
                            <td>{{ ppsn.min_order }}</td>
                            <td>
                                <span>{{ numberFormat(ppsn.discount, 2) }}</span><span>%</span>
                            </td>
                            <td>
                                <span class="network-management">{{ ppsn.network_management ? ppsn.network_management : '0.00' }}</span>
                                <span>%</span>
                            </td>
                            <td>
                                <Select 
                                    v-model="ppsn.administrative_office_id" 
                                    name="Administrative office" 
                                    :error="form.errors[`customer_types.${index}.administrative_office`]" 
                                    :options="reservedNetworkManagements" 
                                    optionName="reserved_network_name"
                                    :isTranslated="true"
                                    class="mb-2"
                                />
                                <MoneyInput 
                                    v-model.lazy="ppsn.administrative_office_percent" 
                                    name="Administrative office percent" 
                                    :error="form.errors[`customer_types.${index}.administrative_office_percent`]" 
                                    thousands="" 
                                    decimal="." 
                                    class="mb-2"
                                />
                                <span class="reserved-amount">{{ numberFormat(ppsn.administrative_office_amount, 4, ',', '.') }}</span>
                            </td>
                            <td>
                                <Select 
                                    v-model="ppsn.commercial_office_id" 
                                    name="Commercial office" 
                                    :error="form.errors[`customer_types.${index}.commercial_office_percent`]" 
                                    :options="reservedNetworkManagements" 
                                    optionName="reserved_network_name"
                                    :isTranslated="true"
                                    class="mb-2"
                                />
                                <MoneyInput 
                                    v-model.lazy="ppsn.commercial_office_percent" 
                                    name="Commercial office percent" 
                                    :error="form.errors[`customer_types.${index}.commercial_office_percent`]" 
                                    thousands="" 
                                    decimal="." 
                                    class="mb-2"
                                />
                                <span class="reserved-amount">{{ numberFormat(ppsn.commercial_office_amount, 4, ',', '.') }}</span>
                            </td>
                            <td>
                                <Select 
                                    v-model="ppsn.technical_office_id" 
                                    name="Technical office" 
                                    :error="form.errors[`customer_types.${index}.technical_office`]" 
                                    :options="reservedNetworkManagements" 
                                    optionName="reserved_network_name"
                                    :isTranslated="true"
                                    class="mb-2"
                                />
                                
                                <MoneyInput 
                                    v-model.lazy="ppsn.technical_office_percent" 
                                    name="Technical office percent" 
                                    :error="form.errors[`customer_types.${index}.technical_office_percent`]" 
                                    thousands="" 
                                    decimal="." 
                                    class="mb-2"
                                />
                                <span class="reserved-amount">{{ numberFormat(ppsn.technical_office_amount, 4, ',', '.') }}</span>
                            </td>
                            <td>
                                <Select 
                                    v-model="ppsn.risk_provision_id" 
                                    name="Risk provision" 
                                    :error="form.errors[`customer_types.${index}.risk_provision_percent`]" 
                                    :options="reservedNetworkManagements" 
                                    optionName="reserved_network_name"
                                    :isTranslated="true"
                                    class="mb-2"
                                />
                                <MoneyInput 
                                    v-model.lazy="ppsn.risk_provision_percent" 
                                    name="Risk provision percent" 
                                    :error="form.errors[`customer_types.${index}.risk_provision_percent`]" 
                                    thousands="" 
                                    decimal="." 
                                    class="mb-2"
                                />
                                <span class="reserved-amount">{{ numberFormat(ppsn.risk_provision_amount, 4, ',', '.') }}</span>
                            </td>
                        </tr>
                    </tbody>
                </table>

                <div class="flex justify-between mt-6">
                    <PrimaryButton class="px-4 open-print-page">{{ __('app.print_download') }}</PrimaryButton>
                    <PrimaryButton :class="{ 'opacity-25': form.processing }" class="float-right" :disabled="form.processing">Save</PrimaryButton>
                </div>
			</form>

It's really nothing special. This is not happening only on this page, but in form every page that i have, like 10 of them.

Haz
Haz
Moderator

Hello,

So many things jump out at me, it's a bit difficult to pin point the exact issue. I don't think you are setting up the form correctly.

const product = props.product
const form = useForm(props.productsPricingSalesNetwork)
const submitRoute = route('network.save', product)

I also don't see where you are correctly binding the values with v-model. I suggest you take a look at the documentation and/or the "Learn Inertia" series here on Codecourse, specifically this episode.

I would also suggest that you spin up a new Laravel Inertia app, and just get a simple form working.

If you are able to share the repo, I'll be happy to take a look for you.

Here's a basic example (assumes you are using Ziggy):

    import { useForm } from "@inertiajs/vue3";

    const form = useForm({
        name '',
        bio: '',
    });

    const submit = () => {
        form.post(route("users.store"), {
            preserveScroll: true,
        });
    };
<form @submit.prevent="submit">
	<input v-model="form.name" type="text">

	<textarea v-model="form.bio" cols="4"></textarea>

	<button type="submit">Submit</button>
</form>

That's basically it.

When rendering the form in edit mode, just set the defaults like so:

    import { useForm } from "@inertiajs/vue3";

    const props = defineProps({
        user: Object,
    });

    const form = useForm({
        name: props.user.name,
        bio: props.user.bio,
    });

The rest stays the same. I hope this helps.

alex
alex
Moderator

I noticed you're also creating a product variable. Is this by any chance the data that isn't being updated on the page?

I'd recommending accessing product directly from props in your template, or use a computed property for this.

shogun
shogun

No @alex, product is not the data that isn't being updated, productsPricingSalesNetwork is. Check my latest posts.

alex
alex
Moderator

Ah sorry – discussion getting pretty big so I missed it!

I think the fact you're using the productsPricingSalesNetwork prop directly within the form is having some effect on the update of this. To be honest, it's not an approach I'd recommend.

Have you tried defining the form in a normal way?

const form = useForm({
    someFieldOne: '',
    someFieldTwo: ''
})

I know you're doing this to share forms, but it might be good to do this to see if Inertia's form helper is preventing this data from being updated on submission.

shogun
shogun

This is an edit page so i need to initially load the data in the form.

I tried something like this, but it is technically the same thing.

const form = useForm({
        customer_types: props.productsPricingSalesNetwork.customer_types
    })

Also, if i redirect to some other route in Laravel after form submits and come back to this page, everything works, and the data is updated. Just redirect back does not work.

alex
alex
Moderator

Hmm yeah, that's typically the approach I'd recommend – actually creating the new object and manually using each field. And that didn't work?

Are you just doing a standard redirect back from the controller? e.g. return back()

shogun
shogun

Yes, just return back(). Now i've tried also redirect()->route('same-route'), but sure does not work.

alex
alex
Moderator

Could you try defining a computed property for the productsPricingSalesNetwork and dumping it on the page to see if it updates?

const productsPricingSalesNetworkComputed = computed(() => props.productsPricingSalesNetwork)

And then somewhere on the page:

{{ productsPricingSalesNetworkComputed }}

Just see if you get the fresh data dumped there with that computed prop.

shogun
shogun

Actually, you read my mind, just did it and it worked :)

shogun
shogun

I just need to replace the data. Let you know soon.

But why is this happening. I do not recall that this was the problem before, like a year ago or so?

alex
alex
Moderator

Great! Let me know how it goes.

I can't recall a specific change to the codebase that would affect this, probably just the reactivity of props changing. Could even be a Vue version difference.

shogun
shogun
Solution

All works!

In script setup

const computedCustomerTypes = computed(() => props.productsPricingSalesNetwork.customer_types)

const form = useForm(props.productsPricingSalesNetwork)

then in template

<span>{{ numberFormat(computedCustomerTypes[index].administrative_office_amount, 4, ',', '.') }}</span>

Tried to attach computedCustomerTypes to the useForm helper directly to avoid using computedCustomerTypes[index] in the for loop, but did not work. Does not matter. Maybe in the future release they fix this.

Thank you!

alex
alex
Moderator

You're very welcome. So glad it's working now 🎉

shogun
shogun

These things did not happen before, like a year ago when i was using inertia, everything was fine. Now I started again using it for some project and decided to use the same form for both create and edit, so that i don't need to repeat the code. V-model binding is just fine. I was checking all this and also the data is inserted fine into the database. I think the problem is somewhere in the form, I try to make edit and create page separately and see if this works.

Haz
Haz
Moderator

I have been out, I just read through the discussion. Glad you have got it working now.

shogun
shogun
const form = useForm(props.productsPricingSalesNetwork)

Here props.productsPricingSalesNetwork has a property customer_types that is an array

I expect for example that the following element changes, but it does not, until i reload the page:

 <span class="reserved-amount">{{ numberFormat(ppsn.risk_provision_amount, 2) }}</span>