Ruby Methods Within JavaScript Within Haml

Ruby methods within Javascript within HAML

Usually, if something is a pain in haml, it means you should refactor the the tricky bit to a helper or partial and call that.

// some_helper.rb
def new_snazzy_select_tag(options = [])
select_tag 'tag_name_here', options.map { |option| [option.id, option.name] }
end

Also, you should use the :javascript filter to render javascript since it will put it in a script tag for you and allow indentation.

Lastly, you can use #{ruby_expression} anywhere in haml, including :javascript filters, which is very handy when you need to output the result of ruby expressions to places that are not directly contents of html elements.

// some_view.html.haml
:javascript
$('#mylink').click(function() {
$('#mylink').after("#{escape_javascript new_snazzy_select_tag(myarray)}");
};

How to access ruby instance variable in Javascript through HAML template

Consider using a nested form...or a similar variation

Here is a link to the rails guide: https://guides.rubyonrails.org/form_helpers.html#nested-forms

It looks liked you want a nested form, and you want to edit comments, using the same form that is used when you want to edit a story (?) or story industry (?). If that's the case then perhaps investigate using nested forms.

Secondly, another gotcha to be aware of: you cannot place one HTML form inside another one: that can't be done. So the javascript workflow you are proposing must render the edit comment partial OUTSIDE the form you have above.........or you can employ a mix of javascript and use the nested forms method above using jquery/javascript. Ryan Bates has devoted two excellent rails casts to this topic - here they are (1) and (2):

But to answer your question:

...it can't be done like that

I don't know if you can actually do it the way you were originally trying to do it - to pass complex ruby objects like that

...but there are solutions:

(A) Render the partials and hide as needed

Why not try a different approach: render the partial directly in your html (but hide it from being seen by the user).

When the button is clicked, you can simply toggle the visibility of the already existing partial.

Since you're using jQuery:

(B) Fetch the partial ayschronously

You can fetch the partial with request in your event handler - stimulus js does this type of workflow very well. You can use the fetch API to get the html partial, or you can use AJAX if you want to support internet explorer etc.

...........you would have to decide whether you want the form nested, or you are happy with completely separate forms.

Dynamically-generated Javascript within HAML

The content of a filter isn’t interpreted as Haml. You can use #{...} for interpolation though, and that’s why you’re seeing the error – the filter sees the #{number} in "#form_#{number}", but the line above where number is defined is simply passed through as it is, not treated as Ruby, so as far as Ruby is concerned number is still undefined.

In this case you could do something like:

:javascript
#{[1,2,3].map do |number|
"$(\"#form_#{number}\").my_method();"
end.join("\n")}

although that’s a bit unwieldy.

A clearer solution might be to create a helper method to create the javascript, which you could call from the filter:

def create_js(arr)
arr.map do |number|
"$(\"#form_#{number}\").my_method();"
end.join("\n")
end

and the Haml would be

:javascript
#{create_js([1,2,3])}

Printing Ruby inside of javascript using haml

Your problem is that you do not want to print those strings; you want to interpolate them. A for-loop just returns the collection it's looping around, which is why you're getting "0..66". You want something that returns the string you were printing.

Instead of a for-loop, try something like this:

(0..@matrix.row_count).map {|i| @matrix.row(i).to_a.to_s }.join(',')

(Incidentally, I would not recommend using Array#to_s for output like this. Its format has changed before and it can change again. I would consider using something more like "[#{matrix.row(i).to_a.join(',')}]", where you explicitly specify how the array should be formatted.)

how to run ruby in haml in javascript definition?

First, let's review what you seem to know:

  1. Ruby requires you to define local variables before you use them.
  2. You can run Ruby code on lines outside of a filter using - ....
  3. You use #{...} markup to interpolate Ruby code inside a filter.

You say you want to run each, but presumably you want output from this; since the result of #{...} is turned into a string and put in your code, what you really want (probably) is map:

%html
%head
:javascript
var foo = [];
#{
limit = rand(4)+3
array = (0..limit).to_a
array.map{ |i| "foo[#{i}] = #{rand(12)};" }.join ' '
}
console.log(foo.length);
%body

Running the above code gives this output:

<html>
<head>
<script type='text/javascript'>
//<![CDATA[
var foo = [];
foo[0] = 2; foo[1] = 0; foo[2] = 11; foo[3] = 8; foo[4] = 0; foo[5] = 1;
//]]>
</script>
<body></body>
</head>
</html>

As you can see, the big #{...} block (which may span multiple lines) runs arbitrary Ruby code. The result of the last expression (in this case the map{...}.join) is converted to a string and placed in the output.

Is there a way to use a Ruby loop inside of HAML's :javascript region?

this one works

%script
- 10.upto(20) do |i|
document.getElementById('aDiv').innerHTML += '#{i}';


Related Topics



Leave a reply



Submit