1

Using Rails 7 (Turbo/Stimulus/RequestJS-Rails)

We're using Stimulus to hit a Plaid endpoint (PlaidLink) to create a connection to a Bank. After the plaid connection is created and returns to our Stimulus controller I'm calling our Rails app using FetchRequest('post'..) to persist the connection. That works as well.

The problem we're having is after the connection is created in our Rails controller, I can see the page rendering in the console (and see the markup in the network tab in the browser) but the page is not rendered to the user.

If I add Turbo.visit("..") to the response.ok block in the stimulus controller, the page is called and rendered correctly, without the notice: message.

I have tried several things in the request, adding turbo:false, responseKind: html I have tried different response_codes from the rails controller

        const request = new FetchRequest('post', '/plaid/linked_items', {
            body: JSON.stringify({
                plaid_item: {
                    institution_id: metadata.institution.institution_id,
                    name: metadata.institution.name,
                    public_token: public_token,
                    link_session_id: metadata.link_session_id,
                    plaid_accounts_attributes: metadata.accounts
                }
            })
        })
        const response = await request.perform()
        if (response.ok) {
            const body = await response.text

            Turbo.visit("/plaid/success")
    respond_to do |format|
      if handler.error.blank?
        if @plaid_item.save
          format.html { redirect_to plaid_linked_items_url, notice: "Plaid item was successfully created." }
          format.json { render :show, status: :created, location: @plaid_item }
        else
          format.html { render :new, status: :unprocessable_entity }
          format.json { render json: @plaid_item.errors, status: :unprocessable_entity }
        end
      else
        @error = PlaidError.create(handler.error.merge(account_id: Current.account.id))

        format.html { render :new, status: :unprocessable_entity, alert: @error.error_message }
        format.json { render json: @plaid_item.errors, status: :unprocessable_entity }
      end
    end
studeba
  • 41
  • 3

1 Answers1

0

Seems to be a pattern: https://stackoverflow.com/a/75579188/207090


https://github.com/rails/request.js#how-to-use

const body = await response.text
// Do whatever you want with the response body

While you can do whatever you want with the body, more importantly, you have to do something with it for things to happen.

const body = await response.text
document.documentElement.innerHTML = body // doing something

Request.JS will render a turbo-stream response, but it will only return the response to you for everything else. So depending on the kind of response you get, you can update the page or Turbo.visit or just update the part you need:

const request = new FetchRequest('get', '/url')
const response = await request.perform()
if (response.ok) {
  const responseBody = await response.text
  // how turbo frame works
  const newDocument = new DOMParser().parseFromString(responseBody, 'text/html')
  const newFrame = newDocument.querySelector('turbo-frame#frame_id')
  const currentFrame = document.querySelector('turbo-frame#frame_id')
  currentFrame.replaceWith(newFrame)
}
Alex
  • 16,409
  • 6
  • 40
  • 56