Question

I have a form where a user can elect to create more input areas (to provide more information). I have a link the user will click on and then the extra form inputs will be created. I'd like to use the rails form helpers so that I don't have to write the html myself. I've tried inserting the form helpers directly into coffeescript and saving the outputted html to a data tag on the link, but I can't get the coffeescript to execute the ruby code and I'm having escaping issues with the data attribute.

Here's the form:

= simple_form_for([@site, @zone]) do |f|
  = f.error_notification

  .form-inputs
    = f.input :site_id

    = label_tag "X"
    = text_field_tag 'x_coords[]'

    = label_tag "Y"
    = text_field_tag 'y_coords[]'

    = label_tag "X"
    = text_field_tag 'x_coords[]'

    = label_tag "Y"
    = text_field_tag 'y_coords[]'

    = label_tag "X"
    = text_field_tag 'x_coords[]'

    = label_tag "Y"
    = text_field_tag 'y_coords[]'

    = link_to "Add Point", "#", id: "add_point", data: { fields: label_tags }

  .form-actions
    = f.button :submit

When a user clicks the "Add Point" link, I'd like to add another block of:

= label_tag "X"
= text_field_tag 'x_coords[]'

= label_tag "Y"
= text_field_tag 'y_coords[]'

label_tags is in application_helper.rb:

def label_tags
  label_tag "Z"
end

The problem is the output for the "Add Point" link is:

<a href="#" data-fields="<label for=" z"="">Z" id="add_point"&gt;Add Point</a>

and the quotation marks are causing the link to come out with the text: "Z" id="add_point">Add Point"

I got the data attribute idea from this screencast

Was it helpful?

Solution 2

Simple solution for me was to replace the double quotes in my generated HTML with single quotes. In code:

= link_to "Add Point", "#", id: "add_point", data: { fields: label_tags.gsub("\"", "'") }

Also, had to use capture and concat in the helper method:

module ApplicationHelper
  def label_tags
    capture do
      concat label_tag "X"
      concat text_field_tag 'x_coords[]'

      concat label_tag "Y"
      concat text_field_tag 'y_coords[]'
    end
  end
end

OTHER TIPS

You cannot execute Ruby code from Javascript. When the page is requested all embedded ruby is evaluated and the results are what you get. The issue that I can see from you paste is that your label block is in the right data attribute but it's not escaped.

What you'll need to do is escape the quotes on the generated HTML going into that field and then unescape them via Javascript. You could use html_escape here like: data: { fields: h(label_tags) } (h is an alias for html_escape or you could do this yourself, manually.

def escape(str)
  str.gsub(/</, "&lt;").gsub(/>/, "&gt;").gsub(/"/, "&quot;")
end

# later in the view for the form
data: { fields: escape(label_tags) }

And then your CoffeeScript would click handler would like:

function unescape(str) {
  return str.replace(/((?:&lt;)|(?:&gt;)|(?:&quot;))/g, function($1) { 
    switch($1) {
      case "&gt;":
        return ">";
      case "&lt;":
        return "<";
      case "&quot;":
        return '"';
    }
  });
}

$("a").on("click", function() {
  var html = unescape(this.data("fields"));
  $(".the-place-to-put-it").html(html);
});

I do not doubt a better solution exists and as of the posting of this answer I have not tested this to work (in theory it should). Ideally, you should just generate the elements with jQuery in Javascript and not depend on this method for doing this - yes, it's duplicate code duplicated between ruby and Coffee.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top