Merus
Merus

Reputation: 8984

Triggering Rails controller action from JavaScript

I have a form that's a part questionnaire, and if certain answers are selected, the form shows additional questions. I need to store the answers to these questions and potentially allow people to change their answers, and I'd prefer to do the decision-making a) in one place, and b) in Rails, so I have a form that examines my @assessment object and shows or hides various questions based on the state of the @assessment object.

I've been trying to get my head around how I use AJAX to set up a round trip. My form is in a partial, so I can reload it as the @assessment object is updated. Most of the examples I've seen involve submitting a form, and using the POST action to pass params to a Rails object then re-rendering a partial using JavaScript. I'm trying to do it through a radio button onClick, but can't work out how I actually get a freshly updated @assessment object from there.

How do I do it? Is it enough of a pain that I should be trying to work out a better way?

Here's a simplified form partial, _form.html.haml:

= bootstrap_form_for @assessment, as: :put, url: project_assessment_path(@project), remote: :true do |f|

  .panel.panel-default
    .panel-heading
      .panel-title Lorem ipsum dolor sit amet
    .panel-body
      = answer_question_1(@project)
  - if show_question(@assessment, :question_2)
    .panel.panel-default
      .panel-heading 
        .panel-title Lorem ipsum dolor sit amet?
      .panel-body
        = f.radio_button :question_2, true, label: "Yes", inline: true, remote: :true
        = f.radio_button :question_2, false, label: "No", inline: true, remote: :true
  - if show_question(@assessment, :question_3)
    .panel.panel-default
      .panel-heading 
        .panel-title Lorem ipsum dolor sit amet?
      .panel-body
        = f.radio_button :question_3, true, label: "Yes", inline: true, remote: :true
        = f.radio_button :question_3, false, label: "No", inline: true, remote: :true

  ...

  - if @assessment.complete?
    - case @assessment.assessment_message
      - when :not_applicable
        .panel.panel-success.hidden
          .panel-body.alert-success
            Duis scelerisque id ipsum et consectetur.
      - when :low
        .panel.panel-success.hidden
          .panel-body.alert-success
            Duis scelerisque id ipsum et consectetur.
      - when :medium
        .panel.panel-warning
          .panel-body.alert-warning
            Duis scelerisque id ipsum et consectetur.
      - when :high  
        .panel.panel-info.hidden
          .panel-body.alert-info 
            Additional information is required:
  - if @assessment.form_required?
    .panel.panel-success
      .panel-heading
        .panel-title Description of Work
      .panel-body
        = f.text_area :aims_hypothesis, label: "Aims/Hypothesis", rows: 4
        = f.text_area :methodology, label: "Brief Description of Methodology", rows: 4
        = f.text_area :significance, rows: 4

...

  = f.form_group do
    = f.submit "Save"

This is contained in this div from edit.html.haml (because @assessment is created automatically with a due date on it, there's no new action)

.row
  #assessment-form.col-xs-12.col-md-11
    = render partial: "form"

Here's the relevant parts of assessments_controller.rb:

  before_action :find_project
  before_action :find_assessment
  before_action :authorised?

  def next_question
    @assessment.update_attributes(strong_parameters)
    respond_to do |format|
      format :html { redirect_to sign_in_path }
      format :js do
        render partial: "update_assessments"
      end
    end
  end

And _update_assessments.js.coffee:

$('#assessment-form').html("<%= escape_javascript (render partial: 'form') %>")

Upvotes: 0

Views: 806

Answers (1)

Fallenhero
Fallenhero

Reputation: 1583

I think your concept is valid and yes you should use AJAX.

Just add and onChange Handler to your radio button and start an AJAX-Post

$(document).on('change', '.your-class-or-id-of-the-radio', function() {
  var element = $(this); // if you need some data from radio button
  $.ajax({
    type: 'POST',
    url: '/path/to/your/controller',
    data: {data: 'you need to pass'}
  });
});

If you need more details just ask.

Upvotes: 1

Related Questions