0

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?

1
  • Gon is for actually passing data for JS from your controller. You could try using capture block for capturing the JS variable and parsing as a Rails variable. Move textToInsert to your controller and trigger for each product. Commented Nov 25, 2015 at 19:12

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

14 Comments

Thanks, it would be great. I'm really not familiar with Ajax and coffee scripts
I added some code, please let me know if it is clear enough.
I'm not sure if I accented it. Idea is that: these divs should be in the same view as pop-up(modal). I don't know if it's matter for you.
the form is remote, so the page shown in the browser is not reloaded; when the js view is rendered, you still have access to everything previously shown, including the modal.
Is it important that these generated divs will be in meals/new.html.erb ( so in the view for a new meal generated by another form_tag)? form_tag inside form_tag, is it ok?
|
0

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

1 Comment

I wrote that I know about it. But how can I solve it?
0

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

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.