Accessing Values Through Ajax Calls and Partials in Rails

Show partial in the same page using ajax request

Rails 5.1 doesn't have a dependency on jQuery. This code:

$('#content').html("<%= j (render 'books') %>");

is jQuery code. If you add the jquery-rails gem and follow the documentation, your code should work.

Using AJAX to insert a partial form

you're trying to pass the entire form builder f through params, which I don't think it's possible.

Since f.input_field is just a helper method to output some HTML, an idea would be to implement directly that HTML into the partial.

so, the "events/user" partial would be:

<input class="string required" id="event_user" maxlength="100" name="event[user]" type="text" value="" />

if this works, you can remove @form = params[:form] from the controller, the locals hash from the view and the ?form=<%=f%> from the AJAX call since aren't needed anymore.

input_field reference at rubydoc

You can also use form_tag helpers too:

<%= text_field_tag(:event,:user) %>

rails 5.1: pass variable to partial through ajax

You should initialize @fbs before rendering after show action. So add @fbs = Setting.find(params[:id]) at the beginning of the show method.

Rendering Rails Partial from AJAX and passing in local variables from AJAX

Client

According to the $.get and $.ajax docs, params will go into the query string part of the URL:

// request to /somethings?a=abc&b=2
$.get('/somethings', {a: 'abc', b: 2})

Server

Query string parameters can be accessed from Rails actions via a Hash-like object called params. [1]

class SomethingsController < ApplicationController
def index
puts params[:a] # if URL was /somethings?a=123, will print 123
end
end

Putting it Together

Let's make a complete example with a partial.

Here is the client code:

// client call to /somethings?name=Something+123
$.get('/somethings', {name: 'Something 123'}, function(data){
$('#target').html(data);
});

Here is the server:

class SomethingsController < ApplicationController
def index
# bind controller variable @name
@name = params[:name]
end
end

Inside the view app/views/somethings/index.html.erb:

<%= render :partial => 'some_partial', :locals => {:name => @name} %>

I've moved the partial rendering into a view. I think rendering partials from views is more standard than rendering partials directly from controllers.

How to render rails partial after a successful ajax POST request?

You need to set your controller up to respond to JS. Remember that js != json.

def create
@run = Run.new(run_params)
@runs = Run.all
respond_to do |format|
if @run.save
format.json { render json: @runs }
format.html { redirect_to :back, :notice => 'Run was successfully created.' }
format.js
else
format.html { render action: "new" }
format.json { render json: @run.errors, :status => :unprocessable_entity }
format.js { render action: "new" }
end
end
end

Not passing a block will trigger the rails default behaviour of rendering create.erb.js.

Do I need an .ajax method if I have a create.js.erb file?

No. You're using the Rails UJS driver to send an ajax request already. Otherwise the response type in the log would be :html.

Other SO questions mention setting the dataType = "script". To the best of my knowledge, I should not need this file.

You're correct. Rails UJS defaults to using a javascript accept type header. Its only if you want a JSON response for example that you need to set the dataType.

How to do render partial on jQuery ajax success method with rails 3

try by rendering the partial from the controller as,

def method_name
render :partial => 'some_partial'
end

and in js,

success: function(result){                      
jQuery("#image_center").html(result);
}

OR ELSE

create a js.erb file corresponding to that action and inside that paste the following:

jQuery("#image_center").html("<%= escape_javascript(render(:partial => 'pages/top_link')) %>");

Access Instance Variable through Ajax Requests and Partials

We need to pass image id when making AJAX calls so that the @image object can be obtained in the views when partials are getting rendered on AJAX completion.

Therefore we fetch the @image using the image_id parameter.

show.html.erb

<div id="cart_form">
<% if @cart_item_collection.include?(@image.id) %>
<%= render 'shared/forms/remove_from_cart', locals: { image: @image } %>
<% else %>
<%= render 'shared/forms/add_to_cart', locals: { image: @image } %>
<% end %>
<p class="error"></p>
</div>

images_controller.rb

class ImagesController < ApplicationController
def show
@image = Image.find(params[:id])
@cart_item_collection = CartItem.where(user_id: current_or_guest_user).pluck(:image_id)
end
end

_add_to_cart.html.erb

<%= form_for(@cart_item, url: cart_item_path, :remote => true do |f| %>
<%= f.hidden_field :image_id, value: @image.id %>
<%= f.submit "Add To Cart" %>
<% end %>

_remove_from_cart.html.erb

<%=button_to cart_item_path(id: @cart_item, image_id: @image.id), method: :delete, :remote => true, class: "icon di_darckblue extra-large button fill", name: 'images' do %>
<i class="di-shopping-cart-up"></i>
Remove From Cart

Adding to cart,

def add_to_cart
@image = Image.find(params[:cart_item][:image_id])
#if @image is present
#your code
#else
#@error= "Item could not be added to cart."
#end
end

create.js.erb

<% if !@error %>
$("#cart_form").html("<%= j render partial: 'shared/forms/remove_from_cart', locals: { image: @image } %>");
$('.error').html('');
<% else %>
$('.error').html(<%= @error %>);
<% end %>

Removing from cart,

def destroy
@image = Image.find(params[:image_id])
#if @image
#destroying @cart_item
#rendering destroy.js.erb
#@cart_item = CartItem.new
#else
@error="Item could not be removed from cart"
#end
end

destroy.js.erb:

<% if !@error %>
$("#cart_form").html('<%= j render partial: "shared/forms/add_to_cart", locals: { image: @image } %>');
$('.error').html('');
<% else %>
$('.error').html(<%= @error %>);
<% end %>

Another way:
As you are just using image id inside the partials:
here we are just passing the image_id in controller and sending it back to front end.

But the only check that we would have to do is checking if the image exists for the image_id passed to controller, as there are chances that user can change the value in front end.

To check that we would have to check for presence of image on every AJAX call made, which makes the first approach more safer. But if that doesn't matter to you then you can go with this approach.

<div id="cart_form">
<% if @cart_item_collection.include?(@image.id) %>
<%= render 'shared/forms/remove_from_cart', locals: { image_id: @image.id } %>
<% else %>
<%= render 'shared/forms/add_to_cart', locals: { image_id: @image.id } %>
<% end %>
</div>

class ImagesController < ApplicationController
def show
@image = Image.find(params[:id])
@cart_item_collection = CartItem.where(user_id: current_or_guest_user).pluck(:image_id)
end
end

_add_to_cart.html.erb

<%= form_for(@cart_item, url: cart_item_path, :remote => true do |f| %>
<%= f.hidden_field :image_id, value: image_id %>
<%= f.submit "Add To Cart" %>
<% end %>

_remove_from_cart.html.erb

<%=button_to cart_item_path(id: @cart_item, image_id: image_id), method: :delete, :remote => true, class: "icon di_darckblue extra-large button fill", name: 'images' do %>
<i class="di-shopping-cart-up"></i>
Remove From Cart

Adding to cart, I render this js.erb file,

def add_to_cart
@image_id = params[:cart_item][:image_id]
#your code

end

create.js.erb

$("#cart_form").html("<%= j render partial: 'shared/forms/remove_from_cart', locals: { image_id: @image_id } %>");

Removing from cart,

def destroy
@image = params[:image_id]
#destroying @cart_item
#rendering destroy.js.erb
end

destroy.js.erb:

$("#cart_form").html('<%= j render partial: "shared/forms/add_to_cart", locals: { image_id: @image_id } %>');


Related Topics



Leave a reply



Submit