3

I am trying to make my page reload after sorting through the new position, either through Javascript or in the Ruby on Rails code.

$("#serialize").click ->
c = set: JSON.stringify($("#sortable").nestedSortable("toHierarchy",
  startDepthCount: 0
))
$.post "savesort", c, $("#output").html("<p id=\"flash_notice\">Saved Successfully</p>")
false

I'm thinking of adding it here

$.post "savesort", c, $("#output").html("<p id=\"flash_notice\">Saved Successfully</p>")
window.location.reload(false); 
false

But it seems like that messes up the order. Here is my rails code

class SiteController < ApplicationController

def savesort
neworder = JSON.parse(params[:set])
prev_item = nil
neworder.each do |item|
  dbitem = Category.find(item['id'])
  prev_item.nil? ? dbitem.move_to_root : dbitem.move_to_right_of(prev_item)
  sort_children(item, dbitem) unless item['children'].nil?
  prev_item = dbitem   
end
Category.rebuild!
render :nothing => true
  end
end

I am also thinking about change render :nothing => true to redirect_to root_url but that doesn't seem to work either.

here is my Routes.rb (Shortened for the sake of space)

locksmithing::Application.routes.draw do
  get "site/home"
  match "/savesort" => 'site#savesort'
    root to: 'site#home'
end

So, where should I add the code to refresh the page? Javascript or in the Site Controller? or is there another solution? Thanks in advance.

2 Answers 2

4

First of all, your $.post call doesn't do what you're probably expecting it to. This:

$.post "savesort", c, $("#output").html("<p id=\"flash_notice\">Saved Successfully</p>")

is the same as this:

$.post "savesort", c

I think your intent is to execute $('#output').html() when the asynchronous $.post call finishes but you need a callback function for that. This part of your $.post:

$("#output").html("<p id=\"flash_notice\">Saved Successfully</p>")

will execute while the $.post call is being built and its return value will be a jQuery object which $.post won't know what to do with. To fix that, just wrap your callback in, well, a callback:

$.post "savesort", c, ->
    $("#output").html("<p id=\"flash_notice\">Saved Successfully</p>")

If you put your window.location.reload(false) immediately after your $.post then you'll reload the page before the POST completes and that's probably not what you want to do and that would explain your "messed up order" problem. Try moving that into the $.post callback so that it will execute after the POST has completed:

$.post "savesort", c, ->
    $("#output").html("<p id=\"flash_notice\">Saved Successfully</p>")
    window.location.reload(false)

Your original code was ignoring the response from SiteController#savesort completely so it wouldn't matter if it returned nothing, returned something, or redirected. The above callback changes still ignore what the controller returns but that's okay and :nothing => true is a sensible thing for it do.

Once you have all that working, you could replace the reload by having your controller return the new data to insert into the page and then the $.post callback could insert that new data into the page. That would be a pretty standard AJAX approach.

Sign up to request clarification or add additional context in comments.

1 Comment

That was some good information, I was able to follow your solution and it worked. Thanks a lot, I am new to Javascript/ Jquery/ Coffeescript so that must have happened when I was converting this from javascript to coffeescript. I got it working and will try the AJAX approach you mentioned.
2

Since you post to your server, your server can send a small partial, to only re-render that part of the page that changed.

Adapt your controller action, not declaring any render/redirect action:

class SiteController < ApplicationController

  def savesort
    neworder = JSON.parse(params[:set])
    prev_item = nil
    neworder.each do |item|
      dbitem = Category.find(item['id'])
      prev_item.nil? ? dbitem.move_to_root : dbitem.move_to_right_of(prev_item)
      sort_children(item, dbitem) unless item['children'].nil?
      prev_item = dbitem   
    end
    Category.rebuild!
  end
end

This will now look for the default view, called savesort.js.erb. In that view you could do anything to overwrite the list of categories.

This file contains pure javascript that is executed in the browser, so for instance:

$("#output").html("<p id=\"flash_notice\">Saved Successfully</p>")

Of course, actually you would want it would also update more relevant parts of the screen.

This is the preferred way, by far. This will only do a partial update of the screen, and will feel most responsive to the user.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.