Marcus Thornton
Marcus Thornton

Reputation: 6193

How to pass parameter to js.erb in Rails?

I want to an ajax request to call user controller's xyz action with the passed parameter stage and then append it on #the_box so that I can perform conditional operation like for stage x append @user.age, for stage y append @user.age+1 and for stage z append @user.age-1. How should I do?

I have a html.erb file contains such code:

<center>
  <%= link_to "A", xyz_user_path, stage: "x", remote: true %>
  <%= link_to "B", xyz_user_path, stage: "y", remote: true %>
  <%= link_to "C", xyz_user_path, stage: "z", remote: true %>
</center>
<div id="the_box"></div>

and users_controller.rb has

before_action :set_user, only: [ :xyz]

def xyz
    respond_to do |format|
        format.js {}
    end
end

private
def set_user
    @user = User.find(params[:id])
end

and this xyz.js.erb is what I have now but cannot deal with parameter so it cannot handle conditional operation

$("#the_box").append("<%= @user.age%>");

Upvotes: 2

Views: 5360

Answers (3)

v2solutions.com
v2solutions.com

Reputation: 1439

Here I'm going to access an instance variable defined in wish_me action.

controllers/jserb_controller.rb code:

class JserbController < ApplicationController
  def index
  end
  def wish_me
    @test = 'Hi how are you?'
    respond_to do |format|
      format.js
    end
  end
end

/views/jserb/index.html.erb code:

<div class="wish-me"></div>
<%= link_to "Wish Me", wishme_path, remote: true %>

/views/jserb/wish_me.js.erb

$(".wish-me").append("<%=j @test %>");

config/routes.rb code:

match '/index' => 'jserb#index'
match '/wishme' => 'jserb#wish_me', :as => :wishme

Now try to hit http://<domain-name>/index and then click on WishMe link. So now you are able to pass instance variable to js.erb and accessed the same.

Upvotes: 0

Richard Peck
Richard Peck

Reputation: 76774

The other answers will help you on here - let me explain them


format.js

When you use format.js to filter the mime types, opening brackets basically tells Rails that you want to perform some custom functionality (and hence it won't load the [action].js.erb as default)

If you want to just invoke [action].js.erb, you'll have to call the following:

respond_to do |format|
   format.js #-> will just call [action].js.erb
end

You'll want to read up more about Rails mime types (how to determine XHR requests) & the respond_to block


@instance_variables

Secondly, you need to consider the role of @instance variables in your application, and consequently, the method in question.

The main issue you have is you're calling @user in a method which doesn't define it - hence you'll likely see the error undefined method ___ for nil:NilClass or similar

You must remember that Rails is just a gem - a series of classes which runs on the Ruby language. This means that each time you wish to perform a method on an "object" / piece of data, you'll have you to declare / create the object in your Rails application:

def xyz
   @user = User.find params[:id] #-> sets the variable for the duration of the "instance"
   ...
end

Please take note of the name of the variable -- an instance variable. By setting @user (instance variables are always defined with an @), you basically give Rails the ability to access the data inside it for as long as the class which defines the variable is invoked.

Basically means that if you set @user = User.find, it will be available through your view & other helper methods called from the instance of the class


Fix

Finally, to address your question directly:

I want to an ajax request to call user controller's xyz action with the passed parameter stage and then append it on #the_box so that I can perform conditional operation like for stage x append @user.age, for stage y append @user.age+1 and for stage z append @user.age-1. How should I do?

#config/routes.rb
resources :users do
   get "xyz/:stage" #-> domain.com/users/:user_id/xyz/:stage
end

#app/views/users/your_view.html.erb
<% links = [["A", "x"], ["B", "y"], ["C", "z"]] %>
<% links.each do |link, stage| %>
    <%= link_to link, xyz_user_path(user, stage: stage), remote: true %>
<% end %>

#app/controllers/users_controller.rb
Class UsersController < ApplicationController
   def xyz
      case params[:stage]
        when "x"
          @user.increment!(:age)
        when "y"
          @user.decrement!(:age)
      end
      respond_to do |format|
         format.js
      end
   end
end

#app/views/users/xyz.js.erb
$("#the_box").append("<%=j @user.age %>");

Upvotes: 6

Lazarus Lazaridis
Lazarus Lazaridis

Reputation: 6029

You should pass the parameter in the helper like this:

xyz_user_path(stage: "x")

And then in your js.erb you can access it like:

<%= params['stage'] %>

Upvotes: 0

Related Questions