How to use inline :confirm option for html helpers

2019-09-06 16:58发布

问题:

I am trying to have an AJAX implementation of record deletion associated with a button. The problem is that ajax:success event doesn't seem to be triggered in such case.

I have implemented the suggestion from this post: Rails :confirm modifier callback?) but I am uncertain if it's the preferred way.

I was wondering if communal wisdom could help in this case. What's the right approach here?

app/views/competitions/show.html.haml:

%td= button_to 'Delete', contender, remote: true, method: :delete, class: 'delete_contender', confirm: 'Are you sure?' if owns?

app/assets/javascripts/competitions.js:

$(document).ready(function() {
  $('.delete_contender').on('confirm:complete', function(e, res) {
    if (res) {
      $(e.currentTarget).closest('tr').fadeOut();
    }
  });
});

app/controllers/contenders_controller.rb:

def destroy
  @contender = Contender.find(params[:id])
  @competition = @contender.competition
  @contender.destroy

  respond_to do |format|
    format.js   
    format.html { redirect_to @competition, notice: "Contender #{@contender.sn_name} has been deleted" }
    format.json { head :no_content }
  end
end

回答1:

The quick answer is: that is not the right approach. The long answer is below.

Instead of using .delete_contender class as an anchor for action binding, I should have used "form[data-remote]" since *button_to* helper generates a form. Also, there is no need to keep the JS hook inside the asset pipeline, it's better to move it to the views and convert to CoffeeScript. The Rails 3 style solution is:

app/views/competitions/show.html.haml:

%td= button_to 'Delete', contender, remote: true, method: :delete, confirm: 'Are you sure?' if owns?

app/views/competitions/destroy.js.coffee:

jQuery ->
  $("form[data-remote]").on "ajax:success", (e, data, status, xhr) ->
    $(e.currentTarget).closest('tr').fadeOut()

app/controllers/contenders_controller.rb:

respond_to :js, only: :destroy

def destroy
  @contender = Contender.find(params[:id])
  @competition = @contender.competition
  @contender.destroy
end