3

I'm building a very simple single-page Rails app with a single form using the remote: true option. Basically, the use selects a few options on the form, and I render a set of products matching these requirements back to the page using the create.js.erb view. So far, so good.

I'd also like to give the user the option to download a CSV list of the products. The problem is, with the remote: true option, I can't figure out how to actually trigger the download. I can use the hack here to route to the correct format and action:

<%= button_tag( 'Download CSV', :value => 'csv', :name => 'format' ) %>

def create
  respond_to do |format|
    format.js
    format.csv { send_data @products.to_csv }
  end
end

This almost works; the correct CSV (text) data is returned in the browser response when I click the "Download CSV" button -- but it doesn't get rendered or trigger a file download, presumably because it's being returned in an AJAX response.

I could make this work by using a link, rather than submitting the form (assuming the action responds to 'GET'):

<%= link_to 'Download CSV', products_path(format: :csv) %>

But then I don't have access to the user data about the product requirements captured in the form parameters.

Is there any way to make this work, or do I need to lose the remote: true and submit the form via HTML (non-AJAX) to trigger the CSV download?

Community
  • 1
  • 1
Sasgorilla
  • 2,403
  • 2
  • 29
  • 56

3 Answers3

1

You can download the file in create.js.erb by using JavaScript code. First give an html a tag as hidden in your html.erb file.

<a id = "download_csv" hidden></a>

Then write the following code in create.js.erb to download the file:

var link = document.getElementById("download_csv");
link.href = '<%= j @filepath %>';
link.download = '<%= j @filename %>';
link.click();

Define @filepath and @filename in your controller.

0

You can send a form as remote but return javascript that will open your download url.

def create
  respond_to do |format|
    format.js
  end
end

create.js.erb

window.open("<%= products_path(format: :csv) %>", "_blank")

This will open up a new tab to download the file then close it leaving the original page.

Alex Kojin
  • 5,044
  • 2
  • 29
  • 31
  • 1
    This issues a GET request to `products_path`, so does not actually submit the form with the parameters needed for the CSV generation. – Sasgorilla Dec 07 '16 at 14:20
0

You can toggle off the AJAX submit of the form and use the name="format" hack to get it working.

On your CSV download button (a submit button), use name="format" and value="csv" and using javascript, remove the data-remote="true" from the form when the button is clicked.

On your regular submit button use name="format" and value="js" and using javascript, set data-remote="true" on the form when the button is clicked.

You'll need to either add authenticity_token: true to the form options or skip authenticity token verification on your controller action for the CSV submit to work.

fyrite
  • 66
  • 2
  • 4