1

I have been following this tutorial https://www.youtube.com/watch?v=TKIbtbYyRdE&list=PL6SEI86zExmvb4qjVHJWrKRQrKjWksQ81&index=34 followed by its 2nd part https://www.youtube.com/watch?v=akrXCho2m6Y&list=PL6SEI86zExmvb4qjVHJWrKRQrKjWksQ81&index=34

I am so Fed up trying to find whats wrong,

<%= link_to "Connect", connections_path, class:"btn btn-primary", data: { controller:"connections", turbo_method: :post, requester_id: current_user.id, connected_id: user.id, connections_target:"connection" } %>

this above link_to uses StimulusJS controller "connections" which should do a POST request

connections_controller.js

import { Controller } from "@hotwired/stimulus";

// Connects to data-controller="connections"
export default class extends Controller {
 static targets = ["connection"];

 connect() {}

 initialize() {
 this.element.setAttribute("data-action", "click->prepareConnectionParams");
  }

 prepareConnectionParams(event) {
    event.preventDefault();

 this.url = this.element.getAttribute("href");

 const element = this.connectionTarget;
 const requesterId = element.dataset.requesterId;
 const connectedId = element.dataset.connectedId;

 const connectionBody = new FormData();

    connectionBody.append("connection[user_id]", requesterId);
    connectionBody.append("connection[connected_user_id]", connectedId);
    connectionBody.append("connection[status]", "pending");

    console.log("Connection Body:", connectionBody);

 fetch(this.url, {
      method: "POST",
      headers: {
        Accept: "text/vnd.turbo-stream.html",
 "X-CSRF-Token": document
          .querySelector('meta[name="csrf-token"]')
          .getAttribute("content"),
      },

      body: connectionBody,
    })
      .then((response) => response.text())
      .then((html) => Turbo.renderStreamMessage(html));
  }
}

after that i have ConnectionsController.rb

class ConnectionsController < ApplicationController 
  before_action :authenicate_user!
 
 def create
 Rails.logger.debug "Params received: #{params.inspect}"

    @connection = current_user.connections.new(connection_params)
    @connector = User.find(connection_params[:connected_user_id])

    respond_to do |format|
 if @connection.save
        format.turbo_stream { 
          render turbo_stream:
          turbo_stream.replace(
 "user-connection-status",
 partial: "connection/create",
 locals: { connector: @connector }
          )
        }
 end
 end
 end

 private
 def connection_params
    params.require(:connection).permit(:user_id, :connected_user_id, :status)
 end
end

When i click the link, it shows Error 400 Bad Request for POST in console and refreshes the page. it was not working so i used Rails.logger.debug "Params received: #{params.inspect}" so in terminal logs it is saying that params is not being sent Params received: #<ActionController::Parameters {"controller"=>"connections", "action"=>"create"} permitted: false>

1 Answer 1

1

You're missing controller for your action:

this.element.setAttribute("data-action", "click->connections#prepareConnectionParams");
//                                               ^^^^^^^^^^^

Here is another example with Stimulus action params:
https://stimulus.hotwired.dev/reference/actions#action-parameters

# there is no need for `turbo_method: :post` since we're doing our own posting
# `connections_target` is also a bit redundant on a controller element itself
<%= link_to "Connect", connections_path,
  data: {
    controller: "connections",
    connections_requester_id_param: 1,
    connections_connected_id_param: 2,
    connections_status_param: "pending",
  }
%>
// app/javascript/controllers/connections_controller.js

import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
  connect() {
    this.element.setAttribute("data-action", "connections#prepareConnectionParams");
  }

  prepareConnectionParams(event) {
    event.preventDefault();
    const { params } = event;
    const body = new FormData();

    body.append("connection[user_id]", params.requesterId);
    body.append("connection[connected_user_id]", params.connectedId);
    body.append("connection[status]", params.status);

    fetch(this.element.getAttribute("href"), {
      method: "POST",
      headers: {
        Accept: "text/vnd.turbo-stream.html",
        "X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').getAttribute("content"),
      },
      body,
    })
      .then((response) => response.text())
      .then((html) => Turbo.renderStreamMessage(html));
  }
}

I have not looked at the tutorial, just make sure all that ^ leads to something useful, because you can accomplish the same thing with a regular form and much less code:

<%= button_to "Connect", connections_path, 
  params: {
    connection: {
      user_id: 1,
      connected_user_id: 2,
      status: "pending",
    }
  }
%>

This will send a TURBO_STREAM POST request with the same params and will handle turbo_stream response for you.

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.