inertiajs / inertia-laravel

The Laravel adapter for Inertia.js.
https://inertiajs.com
MIT License
1.98k stars 222 forks source link

Redirect back with updated data #170

Closed wassim closed 3 years ago

wassim commented 3 years ago

I'm submitting a form to update some user's data. My controller is updating data fine in db, but my Vue doesn't get updated data back without a "manual" refresh.

Parent component:

<my-form :user="$page.user" />

Form component:

...
methods: {
    submit() {
        this.form.post(route('some.route'), {
            preserveScroll: true
        })
    },
},

My form controller:

...
$user->save();
return redirect()->back()->with('user', $user); // redirect with updated user

Am I missing something here?

reinink commented 3 years ago

If you're using Jetstream, this is because of the resetOnSuccess option is set to true by default. Do this instead:

methods: {
    submit() {
        this.form.post(route('some.route'), {
            preserveScroll: true,
            resetOnSuccess: false,
        })
    },
},
wassim commented 3 years ago

@reinink I'm indeed using Jetstream and adding "resetOnSuccess: false" doesn't fix my issue.

reinink commented 3 years ago

Hmm, gotcha. I am curious, why are you doing this?

return redirect()->back()->with('user', $user); // redirect with updated user

You don't really need to do that, assuming that your edit page is already loading your user. This should be sufficient:

return redirect()->back();

Also, I generally discourage doing this:

<my-form :user="$page.user" />

Better to do this:

<my-form :user="user" />

<script>
export default {
  props: {
    user: Object,
  }
}
</script>

Although that shouldn't make any difference, since $page.user is also reactive.

When you look at the response in the devtools, are you seeing the updated user data coming back in the page props?

wassim commented 3 years ago

Hmm, gotcha. I am curious, why are you doing this?

I tough that would fix my issue. I removed it.

When you look at the response in the devtools, are you seeing the updated user data coming back in the page props?

Yes, I can see the updated user data in devtools coming back.

reinink commented 3 years ago

Can you try using a regular prop instead of using $page.user?

wassim commented 3 years ago

Okay I fixed it. You where right about "resetOnSuccess: false" but I had to do it like so:

methods: {
    submit() {
        this.form.post(route('some.route'), {
            preserveScroll: true
        }, {
            resetOnSuccess: false
        })
    },
},

Sorry for the trouble, and thank you for Inertia!

reinink commented 3 years ago

Ugh, silly me. 🤦

Glad you got it figured out. 👍

mo3auya91 commented 3 years ago

Hi @reinink , I do not want to redirect from server, just return a json response. how can I handel it in Inertia here is my code in vue

methods: {
    submit() {
      this.$inertia.post(url, this.form, {
        preserveScroll: true,
        resetOnSuccess: false,
      })
    }
  }

and in laravel

public function store(Request $request)
    {
        // code 
        return response()->json('my json response here');
    }

I just want to return json from server and parse it in vue component I want to stay in the page this is what I got when I do this

Screenshot 2020-10-22 at 00 08 57
reinink commented 3 years ago

@mo3auya91 Just use a regular xhr/fetch request for this. Don't use Inertia.js.

mo3auya91 commented 3 years ago

thanks

vanderb commented 3 years ago

Adding resetOnSuccess to the request-options didnt do the trick for me.

The solution is to add it to the form-option instead to the request-option. https://jetstream.laravel.com/1.x/stacks/inertia.html#form-validation-helpers

Arfat-Mughal commented 3 years ago

That's not a good or proper way but it's work for me.

Using Vue & inertia in laravel no Jetstream.

return redirect()->back()->withErrors(['company'=>$company]);

lolzzzzz i got this company via errors.company

heychazza commented 3 years ago

Hi @reinink, I know this is an old issue but hope to get some further clarification.

I'm currently building an application where upon submitting the form, the server does a third party api request (through a third party class).

I have a "connected" prop that's returned on the form submit, however I'm unable to v-if this correctly.

I have my form set to not redirect as I show something below it (response from third party).

How can this be achieved, or is this something currently not available?

Thanks for everything you've done, InertiaJS seems FANTASTIC so far, 10/10.

reinink commented 3 years ago

@heychazza Hmm, I'm honestly not following what you're trying to do. However, if you're trying to redirect away from the app, and then redirect back to the same page with an updated connected prop, that should just work.

Howe are you doing the third party API request? Is that just server-side, or are you redirecting (doing a location visit) client-side?

heychazza commented 3 years ago

@heychazza Hmm, I'm honestly not following what you're trying to do. However, if you're trying to redirect away from the app, and then redirect back to the same page with an updated connected prop, that should just work.

Howe are you doing the third party API request? Is that just server-side, or are you redirecting (doing a location visit) client-side?

Hi, sorry if I didn't clarify correctly.

So, I currently wish to do the following:

  1. User enters a game server IP address.
  2. User submits form.
  3. Server does a request to a third party (with api key).
  4. Server sends back data to client, showing the result.

I want to be able to server -> client (display form) -> server (post data) -> client (result)

I tried to return Inertia::render(), am I doing this wrong? V-if wouldn't display

herpaderpaldent commented 3 years ago

Maybe i can be of help. I need to something similiar in my app. I am currently solving it via a normal axios call towards a controller of my app. Within my controller i do the Request towards the third party and awaiting the repsonse, then returning the response. This would be the result of the axios call. Simply map the response within your front-end framework and you are golden. There is no need to involve inertia in these kind of operations.

Just as a general Path image

heychazza commented 3 years ago

Maybe i can be of help. I need to something similiar in my app. I am currently solving it via a normal axios call towards a controller of my app. Within my controller i do the Request towards the third party and awaiting the repsonse, then returning the response. This would be the result of the axios call. Simply map the response within your front-end framework and you are golden. There is no need to involve inertia in these kind of operations.

Just as a general Path image

Thank you, I did see axios when diving into it, but wasn't sure if there was an Inertia way that could result in a cleaner approach for my code without much 'manual' work.

Or if not, if this is something that can be implemented / fixed somehow. I always prefer to go with solutions that can be integrated within the framework or library itself.

Will defo note this one though, thank you a ton! Appreciate it. Could this be reversed and spoofed?

mendela1992 commented 2 years ago

@reinink Would Inertia be able to figure out updated data for the relationships associated with a parent model when updating my vue? In my case, I am updating a related model, which affects a parent model from my vue. I am making a PUT request using Inertia form helper and the updated information of the parent is showed directly on my vue page but for the related model, data is not updated (I have the reload the page).

Any suggestion?

DavidGarrido commented 2 years ago

Buen dia, he intentado las opciones que pones y me funcionan porque si se me actualiza la informacion, pero como hago para que se limpien los campos del formulario?

quantumwebco commented 2 years ago

I have the same problem as @mendela1992 I have a modal with a form that creates a one to many relationship ($company->departments()->create($data)) by posting to the store route of the relationship model and return back() When I dump the data from the show() method in the CompanyController after return back, the data is all there, in the dev tools network tab the data is there, the new relationship is added, but it doesn't refresh on the page Is there a way to "deep" watch page props and have them update automatically?

As a workaround in my data() I have departments: this.company.departments, and then onSuccess: () => this.departments = this.company.departments

FaycalBorsali commented 2 years ago

Hello everyone, I know this is an old issue but I faced the same problems described above and found a 'sneaky' problem on my code that helped me overcome the issues described.

TL;DR : on redirect()->back() the vue components are not mounted, they are just updated

My setup :

  1. Laravel + Inertia (vue) using Jetstream
  2. A page view called Dashboard that has a MyForm component
  3. In MyForm's mounted() hook, I initialize some boolean variable to decide what to show (using v-if)
  4. When the form is submitted, and laravel redirects back, the component remains the same, so the mounted() method is not hit, hence my boolean variable is not updated (even though the conditions that should make it change are correctly loaded as I could find my vue devtools), hence my view doesn't update.

Once I understood the problem, my solution was straightforward.

  1. I moved the logic from my mounted hook to a custom method, let's name it initVariables
  2. In both the mounted and updated hooks, I call this.initVariables()

EDIT

In my specific use cas, I was better off calling my initVariables from a watcher than in my updated

d-damien commented 1 year ago

Similar problem here. Solution similar to @quantumwebco's plus model refresh.

Server side : $question->refresh(); return redirect()->back(); Client side : onSuccess: _ => this.form.answers = this.question.answers

marklawntalk commented 1 year ago

Had similar problem. And reseting the field resolved the issue.

onSuccess :  (response) => {
      form.reset('field_name')
  }
ZodexNL commented 1 year ago

Hello everyone, I know this is an old issue but I faced the same problems described above and found a 'sneaky' problem on my code that helped me overcome the issues described.

TL;DR : on redirect()->back() the vue components are not mounted, they are just updated

My setup :

  1. Laravel + Inertia (vue) using Jetstream
  2. A page view called Dashboard that has a MyForm component
  3. In MyForm's mounted() hook, I initialize some boolean variable to decide what to show (using v-if)
  4. When the form is submitted, and laravel redirects back, the component remains the same, so the mounted() method is not hit, hence my boolean variable is not updated (even though the conditions that should make it change are correctly loaded as I could find my vue devtools), hence my view doesn't update.

Once I understood the problem, my solution was straightforward.

  1. I moved the logic from my mounted hook to a custom method, let's name it initVariables
  2. In both the mounted and updated hooks, I call this.initVariables()

EDIT

In my specific use cas, I was better off calling my initVariables from a watcher than in my updated

Thanks for the clear explanation. I had the exact same problem as you. Thanks for providing a clear solution!

tharaka626 commented 6 months ago

In Vue3, Just add preserveState: false inside the view action.

Example:-

    form.delete(route('tour_additional_service.destroy', id), {
        preserveScroll: true,
        preserveState: false,
        onSuccess: () => closeModal()
    });