-1

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.

  • I have not been able to get Inertia.js to work work within this create action, using a Rails redirect_to().
  • So I am currently passing 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?

2
  • Please include the relevant code in the question itself. Why should people both to help you if you can't be bothered to do more than just drop a link to your repo? Commented Mar 4 at 10:45
  • @max I have added code snippets. Thank you Max. Commented Mar 4 at 13:36

1 Answer 1

0

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>

https://inertia-rails.dev/guide/links

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.