简体   繁体   中英

Rails - how put javascript variable into erb code

I've seen some similar question, but still don't know how achieve my goal. I want to do that thing:

  1. Display modal with products represented by divs.
  2. User choose some products (I add .active class to chosen products)
  3. Then I use jQuery to make array of chosen products ids.
  4. In the end I want to create div for each product, which will be include some informations about this product from database. I'm using js .append() to do it. And here is a problem.

This code is in my script tag in proper view.

    var chosen_products_array;

    $('.product-to-choose').click(function() {
        $(this).toggleClass("active");
        $(this).find('i').toggleClass("visible");
    });

    $('#chosen-products-confirm').click(function() {
        var chosen_products = $('.product-to-choose.active');
        chosen_products_array = jQuery.makeArray( chosen_products );
    });

    $('#confirm').click(function() {

        var textToInsert = '<div><h4>Products:</h4>';
        $.each(chosen_products_array, function(count, item) {
            var id = $(item).attr('id').substr(8); // id is product_number
            textToInsert += '<div><li name="chosen-product"> <%= current_user.products.find(' + id +').name %></li></div>';
        });
        textToInsert += '</div>';
        $('#div-example').append(textToInsert);
    });

My controller create action:

def create
@meal = current_user.meals.build(meal_params)
if @meal.save
  current_user.type_tags.each do |type_tag|
    key = "type#{type_tag.id}"
    if params[key]
      @meal.type_tags << type_tag # zapis do bazy danych
    end
  end
  flash[:success] = "Create new meal!"
  redirect_to meals_path
else
  #render 'meals/new'
end

end

This line generates error:

textToInsert += '<div><li name="chosen-product"> <%= current_user.products.find(' + id +').name %></li></div>';

Error:

Couldn't find Product with 'id'=+id+ [WHERE "products"."user_id" = ?]

I know there is a problem in passing js variables to rails erb, but how can I solve it in this case? I tried with gon too.

In my controller, I added:

gon.products = current_user.products

and then try

alert(gon.products)

it's ok - array of objects, but when I try

alert(gon.products.find(1))

it doesn't work.

Have you got any idea how can I put this javascript id variable to erb code? Or maybe is any different solution?

Probably the best would be to add a remote form (it may be hidden) that posts whatever you want (javascript values) and then it is handled by a controller. Then you can render it with js views.

This would probably be the most "rails-like" solution.

Here's some code:

In the routes:

resource :my_form, only: :create

In the view:

<%= form_tag(my_form_path, remote: true, method: :post) do %>
  <%= hidden_field_tag :val %>
<% end %>

You alter the val dynamically by javascript, and submit the form whenever you want to.

Then, in the controller you have something like this:

respond_to :js

def create
  # do something with params['val']
  @my_val = params['val']
end

And you would also add create.js.erb view, where you could add some javascript that can use any of the instance variables created in the controller.

//create.js.erb
$('#someElement').html('<%= @my_val %>');

Let me stress if it is not clear, the form is remote (ajax), so it is sent in the background and the page is not reloaded.

When the browser receives the response, it may contain any javascript you decide to render (the contents of create.js.erb), and then the browser executes that javascript.

So, you can add there any jquery commands with arguments that you changed dynamically by rails, or you could also render html partials and replace any elements with them, like this:

//create.js.erb
$('#my_id').html('<%= j(render partial: 'my_form/_some_partial.html.erb', locals: { my_val: @my_val }) %>');

More details on Working with JavaScript in Rails


UPDATE

Another, inferior but simpler to implement solution would be to always render all products, but have them hidden initially, and then show them by jQuery on demand. You would just need to add appropriate css classes or data attributes to those products, as well as the links you use to select them.

The problem is that erb code is evaluated on the server before the browser even fetches the javascript file, so it doesn't make sense to use this way. It's recommended that you only use erb in your javascript for simple things like asset_path

I think first make your model visible to the browser as js variable(json object) . Some thing like below at the end of your view file(below is the haml syntax):

:javascript

   var userProducts        = #{@current_user.products.to_json};

Then use it in javascript expression

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM