I have a Rails 8 application which is using Inertia.js and Vue. I am not sure how to implement a redirect_to()
request using Inertia.js within Rails. My attempts are not working. I am using https://github.com/skryukov/inertia_rails-contrib
in integrating Inertia.js into Rails.
Github repo is at https://github.com/Chrisgo-75/rails8_inertiajs_vuejs
The worflow is
a) HTML button "Add to Cart" is found on /app/frontend/pages/Store/Index.vue
.
# /app/frontend/pages/Store/Index.vue
<template>
<button
@click="addToCart(product.id)"
class="ml-4 rounded-lg py-1 px-2 text-white bg-green-600"
>
Add to Cart
</button>
</template>
<script setup lang="ts">
import axios from "axios";
import { router } from '@inertiajs/vue3';
const addToCart = async (productId: number) => {
try {
const response = await axios.post('/line_items',
{ product_id: productId },
{ headers: { 'X-CSRF-Token': csrfToken } } // Include CSRF token
);
alert('Product added to cart!');
// Extract the cart ID from the response.
const cartId = response.data.cart_id;
router.visit(`/carts/${cartId}`);
} catch (error) {
console.error('Error adding to cart: ', error);
alert('Failed to add product to cart.');
}
};
</script>
b) Clicking the "Add to Cart" button goes to /app/controllers/line_items_controller.rb
Create Controller action.
redirect_to()
.cart_id
back to Vue as JSON.# line_items_controller.rb
def create
product = Product.find(params[:product_id])
@line_item = @cart.line_items.build(product: product)
if @line_item.save
# redirect_to @line_item.cart, notice: "Line item was successfully created."
# redirect_to @cart, notice: "Cart was successfully updated."
# redirect_to inertia: cart_path(@cart), notice: "Cart was successfully updated."
render json: { cart_id: @cart.id }
else
# redirect_to new_line_item_url, inertia: { errors: @line_item.errors }
# render inertia: "Carts/Show", props: { cart: @cart, errors: @line_item.errors }
render json: { errors: @line_item.errors.full_messages },
status: :unprocessable_entity
end
end # END def create
c) The LineItems Controller Create action passes cart_id
back to /app/frontend/pages/Store/Index.vue
where it performs router.visit('/carts/${cartId}')
.
Does anyone have a solution for implementing a redirect_to()
Inertia.js request within Rails?
Axios does redirect but you have to handle the final response yourself, which is what you're doing when you render
instead of a redirect.
Inertia provides an api for manual requests and it handles redirects and page updates. Instead of axios.post
do this:
<template>
<button @click="addToCart(product.id)">
Add to Cart
</button>
</template>
<script setup>
import { router } from '@inertiajs/vue3';
const addToCart = (product_id) => {
router.visit('/line_items', {
method: 'POST',
data: { product_id },
});
}
</script>
https://inertia-rails.dev/guide/manual-visits
Or use Link
component:
<template>
<Link
href="/line_items"
method="post"
:data="{ product_id: product.id }"
>
Add to Cart
</Link>
</template>
<script setup>
import { Link } from '@inertiajs/vue3'
</script>