slhck
slhck

Reputation: 38682

What is the proper way of passing HTML from the controller to Javascript?

In my application, I let users input annotations, which are potentially unsafe. When I render them in my view, the following shows the annotation nicely:

<%= simple_format h annotation.body %>

It preserves line breaks but also escapes HTML properly. Now, I need to render this body in an overlay, which is created by Javascript. Right now, I fetch my annotations through JSON by calling the following from the controller:

def index
  # ...
  respond_to do |format|
    format.json { render :json => @annotations }
  end
end

And create the overlay like this (very simplified example):

$.getJSON(this.annotations_url, function(data) { 
  $.each(data, function(key, val) {
      annotation = val;
      this.div_body.html(annotation.body);
      // ...

Of course, the resulting HTML will not be escaped properly and the line breaks aren't preserved as well.


Now, I don't feel like using pure Javascript to do the escaping and line break conversion because it feels like I wouldn't be DRYing a lot if I did so. It seems hard to maintain and clutters the whole code.

Can't I somehow send the safe HTML body from the controller through JSON? It looks as if the ERB simple_format and h methods are only available in views.

Or should I really do everything in Javascript?

Upvotes: 2

Views: 153

Answers (2)

fguillen
fguillen

Reputation: 38792

I think you can use the helpers every where just calling them by their long name:

ActionController::Base.helpers.simple_format str
ERB::Util::html_escape str

Once you have this you can customize your Model.to_json behavior to include an already parsed version of the Model.body.

Of course there are two problems with this approach:

  1. Rails dependency in your Model
  2. Adding View behavior in your Model

But sometimes trying to avoid these issues is bringing more complexity than clarity.

Upvotes: 1

Marlin Pierce
Marlin Pierce

Reputation: 10089

You can return JSON from erb templates just as you would for html. Instead of returning JSON in the controller, let it fall through doing no rendering, just like html responses. Instead of naming the view index.hmtl.erb, name it index.json.erb.

I'm not sure that's the best cleanest way. It is the only way Rails has provided simple_format for responses html or other.

Upvotes: 0

Related Questions