7

I have a link which, when clicked, will make an AJAX call. This AJAX call will result in a modal showing up.

= link_to edit_evaluation_path(evaluation), remote: true

However, when trying to open a new tab from the link (by clicking it with the middle mouse button, for example) I've been getting a ActionController::UnknownFormat: ActionController::UnknownFormat error, because the action is not expecting to respond with a html format. Here's the respond_to code from the corresponding action:

respond_to do |format|
  format.js
end

How can I prevent the user from opening the link in another tab or window? Am I obliged to change the link_to to a button_to? Thanks!

sauronnikko
  • 4,665
  • 5
  • 31
  • 47

2 Answers2

6

I've made created Javascript only solution for this problem in which I ran today.

$.each($("a[data-remote='true']"), function(i, val) {
  $(val).data("url", $(val).attr("href")).attr("href", "javascript:void(0);")
});

$.rails.href = function(el) {
  var $el = $(el);
  return $el.data('url') || $el.data('href') || $el.attr('href');
}

It will replace all data-remote links on the site directly

Sumy
  • 93
  • 2
  • 6
  • This doesn't work when you have more than one action on the page. The second time you click it, it throws `GET javascript:void(0); net::ERR_FAILED` – bonafernando Apr 16 '20 at 18:53
  • I'm sorry for the comment above. The thing is that the response from the remote action used to also contain this script inside. So, this can be improved to identify the already updated `url` field and skip them. – bonafernando Apr 16 '20 at 20:10
1

I have devised a workaround for this. This comprises of two steps:

The jquery-ujs function that determines target url of a remote link can be overriden. So we override it to pick a data attribute before we check for href.

$.rails.href = function(el) {
    var $el = $(el);
    return $el.attr('data-url') || $el.attr('data-href') || $el.attr('href');
}

Next, We create a custom helper similar to link to that outputs the url in data attribute rather than href.

  def pseudo_link_to(name = nil, options = nil, html_options = nil, &block)
    html_options, options, name = options, name, block if block_given?
    options ||= {}

    html_options = convert_options_to_data_attributes(options, html_options)

    url = url_for(options)
    html_options["data-href".freeze] ||= url
    html_options['href'] = 'javascript:void(0)'
    content_tag("a".freeze, name || url, html_options, &block)
  end

Note that actual href is javascript:void(0) which is a javascript no-op.

Now, all you have to do is use pseudo_link_to helper in your rails views instead of link_to.

Community
  • 1
  • 1
lorefnon
  • 12,875
  • 6
  • 61
  • 93