简体   繁体   中英

How to submit form and update element on the page without refresh, in Rails 4

I'm having a lot of trouble trying to do something that I imagine would be fairly simple.

I have a list of items, let's say, todos. At the bottom of that list I have a text field where I add new items to that list. I want to make it so that the new items are added to the bottom of that list dynamically, without a full page refresh, like in a chat window.

I made the submit form remote: true and it successfully submits without reloading the page, but I can't get the new item to appear at the bottom of the list at the same time. I have to refresh the page to see the changes.

I tried a few different approaches I found on SO (there's no shortage of similar questions here) and the web, and even a gem called Sync, but each of them had errors and problems of their own and I couldn't get any to work properly. Each of them could be its own SO question. So instead I ask: Is there a "recipe" that is sure to successfully implement this in Rails 4?

let's say, now you have a user form to submit,

<%=form_for @user,remote: true%><%end%>

And you also have a controller,

UsersController

In your controller, you have a function,

def create
  #something
end

which is for the form.

the only thing you need is to modify the function like

def create
  #something
  respond_to do |format|
    format.js
    format.html
  end
end

then in your view side, under directory of view/users/ , create a create.js file, in the file, you can do the js action, like get the new record, and append the new record to the users list.

reference:

http://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html#form-for

There are various ways to do what you are asking. My approach would be:

  • Create an AJAX call to the controller that passes the parameters of the form

  • Inside the controller, you save/update things and then return a JSON object

  • On the success callback of the AJAX function, you append a list item/table row, using the object values

The code could be something like this:

model.js

$(function() {
  $("#submit_button").on("click", function(event) {
    event.preventDefault();
    $.ajax({
      type: "POST",
      url: "your_controller_url",
      data: "your_form_data"
      success: function(result) {
        // Append the result to a table or list, $("list").append(result)
      },
    });
  });
});

controller.rb

def your_action
  # Do your stuff
  # return JSON to the ajax call
end

Well, this is just a skeleton. I prefer doing things this way. (Because i hate the js.erb approach)

Here is rails 5, hope it will help someone ( it still works on rails 4 ):

Try this ajax example:

In 'routes.rb':

# set the route that ajax can find the path to what controller in backend
get   '/admin/some_great_flow',   to: 'great_control#great_flow'

In 'great_control_controller.rb' controller:

 # this function in controller will response for ajax's call
 def great_flow
    # We can find some user or getting some data, model here.
    # 'params[:id]' is passed by ajax that we can use it to find something we want.
    @user = User.find(params[:id]) 

    # print whole data on terminal to check it correct.
    puts YAML::dump(@user.id) 

    # transform what you want to json and pass it back.        
    render json: {staff_info: @user } 
end

In 'app/views/great_control/index.html.erb' view:

<div>
     <label>Staffs</label>
     <%=select_tag(:staff, options_from_collection_for_select(@staffs, :id, :name), id:"staff_id", required: true)%>
</div>
<script>
//every time if option change it will call ajax once to get the backend data.
$("#staff_id").change(function(event) {
    let staff_id = $("#staff_id").val()
    $.ajax({
        // If you want to find url can try this 'localhost:prot/rails/info/routes'
        url: '/admin/some_great_flow', 
        type: 'GET',
        dataType: 'script',
        data: { id: staff_id },
        // we get the controller pass here
        success: function(result) {
             var result = JSON.parse(result);
             console.log(result['staff_info']);
             // use the data from backend for your great javascript.
        },
    });
});
</script>

I write it for myself.

You can see the changes using javascript. For eg lets consider a controller Mycontroller with action index and you are submitting form on index. Then create a file in views my_controller/index.js.erb

To reflect changes use javascript in this template. Definately remote sends the ajax call, so to see the changes you need some manipulation using javascript.

Thanks

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM