0

I have two buttons that both work independently below. One button creates a relationship between the user and the step via ajax. Another button executes a function, that chooses which bootstrap modal to display(success or failure). I need the functionality of both buttons in one single button, as opposed to two separate buttons. However, for example, when I try to add class data-toggle="modal" to the the ajax button, the button no longer is capable of creating a relationship and the data-modal does not work.

Here is a working button, of which functionality I am trying to replicate:

<div data-toggle="modal">
  <%= link_to_function "check answer", 'execute();', class: "btn btn-success"%>
</div>

Here is the execute(); function from above, which isn't all together relevant other than it takes true or false as an argument and shows the appropriate modal based upon which.

if(checked)
            {
                //display correct-answer dialogue
                $('#modal-simple-success').modal('show')              
            }
            else
            {
                //display wrong-answer dialogue
                $('#modal-simple-failure').modal('show')
            }

I need the functionality of above to work for the below button - basically the button below renders an ajax button that creates or removes a relationship. When I try to add data-toggle="modal" to this, it no longer builds the relationship and the ajax doesn't work. I need all three functionalities to work(build the relationship[below], initiate execute function [above], and then display the modal [above].

<div id="attempt_step">
    <% if current_user.attempted_step?(@step) %>
       <%= render 'remove_attempt' %>
    <% else %>
       <%= render 'attempt_step' %>
    <% end %>
</div>

Here is the specific form for ajax for the create relationship:

  <div class="checkAnswer">
    <%= form_for(current_user.user_steps.build(step_id: @step.id), remote: true) do |f| %>
      <div><%= f.hidden_field :step_id %></div>
      <%= f.submit "check answer", class: " btn btn-large btn-primary" %>
    <% end %>
  </div>

Here is the "create" javascript for ajax

$("#attempt_step").html("<%= escape_javascript(render('steps/attempt_step')) %>")

Here is an example idea of what I am looking for, but does not work:

<div id="attempt_step" data-toggle="modal">
 <%= link_to_function "check answer", 'execute();' do %>
    <% if current_user.attempted_step?(@step) %>
       <%= render 'remove_attempt' %>
    <% else %>
       <%= render 'attempt_step' %>
    <% end %>
 <% end %>
</div>

How can I achieve the functionality of both buttons (ie making the above work)?

Sean L
  • 827
  • 1
  • 11
  • 22

1 Answers1

0

It seems you are a little unfamiliar with Rails best practices.

Here are some suggestions:

  1. link_to_function is deprecated in Rails 4. Use ujs instead. More info here:
    Status of Rails' link_to_function deprecation? http://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html#unobtrusive-javascript

  2. In your form for you have current_user.user_steps.build(step_id: @step.id). This should be done in the new action of your controller(Or whatever action is rendering the page with the buttons on it). This model should probably be called step instead of user_step i.e.

    class StepsController < ApplicationController  
      def new  
        @step = current_user.steps.new  
      end  
    end  
    
  3. You are using a form_for with remote: true option. This will send an ajax request to your step controller and hit the create action. Because this request is sent by ajax, Rails will automatically look for a js file to render called create.js.erb or create.coffee in views/steps direcory. That means that you can put js or coffeescript in this file to be ran after the code in your create action is ran. In your case you can run something along the lines of this:

    # Here you can check anything on the DOM.  Check for a value or check if the user checked a checkbox for example.
    if ($("#id-of-element").val() == whatever_you_want_it_to) {
      $('#modal-simple-success').modal('show');
    } else {
      $('#modal-simple-failure').modal('show');
    }
    

    Then this one form submit button will hit your create action in your controller, create the related step record, render the js file, run the js conditional function and reveal the modal depending on the conditional.

    Here is more info on how Rails renders js files after remote requests to controller actions:
    How do I get my js.erb file to render?

Community
  • 1
  • 1
mpiccolo
  • 662
  • 5
  • 14
  • Hi, to clarify - the display modal logic is based on whether a user enters a value right within the page itself, and not based on the success of the create action. For example if the user hits the button I want it first create the relationship via ajax (create.js.erb) and then to check that their input of 4 == the answer 4 (true or false is passed to execute function above). If successful then display success modal logic. – Sean L Oct 17 '13 at 02:24
  • Is this value passed to the controller as part of the form? – mpiccolo Oct 17 '13 at 02:31
  • No, the if(checked) function from above - pulls a number from a the page, and if it matches a specific number - true is passed to the function, and the success modal should display. If not, the failure modal should be displayed. Net-net: this is all done on javascript within the page itself. – Sean L Oct 17 '13 at 02:37
  • If you have a form remote true then it is hitting a controller action create. Your controller create action is creating the relationship. Rails will automatically render a file called create.js.erb if it exists in the proper view directory. It will run the js code above on the DOM so you can use your function in that file. – mpiccolo Oct 17 '13 at 02:41
  • Take a look here to see an explanation about rails controller action rendering js files. http://stackoverflow.com/questions/8390358/how-do-i-get-my-js-erb-file-to-render – mpiccolo Oct 17 '13 at 02:49
  • I am not sure i follow but I am thinking about trying this though: if first button is clicked trigger the second button ie - $( "#foo" ).trigger( "click" ); – Sean L Oct 17 '13 at 03:29
  • What you are describing would work but it is not rails best practices. I will update my answer to describe a little better but I don't think you are going to like it because it is going to involve several links and quite a bit of reading. – mpiccolo Oct 17 '13 at 03:50