我查看了数十个堆栈溢出帖子,但没有找到有效的解决方案,这就是为什么我要寻求一个其他方面有据可查的用例。
我有一个按钮可以执行此操作。
- 点击后,调用自定义 Controller 方法来更新模型和做其他事情
- 调用 javascript 函数来更新页面而不重新加载它 (ajax)
现在,我能够调用自定义 Controller 方法的唯一方法是通过这种感觉非常笨拙的方法。我已将其简化为尽可能简单。
路线.rb
match 'admin/:id/toggleAdmin' => 'admin#toggleAdmin', via: [:patch, :put], as: :toggleAdmin
list.html.erb
<td><%= link_to "Toggle Admin", toggleAdmin_path(id: user.id), method: :patch %></td>
admin_controller.rb
class AdminController < ApplicationController
def toggleAdmin
idToToggle = User.find(params[:id]).id
if idToToggle == current_user.id
redirect_to admin_list_path, danger: "You tried to make yourself a normal user! Don't do that!"
else
User.find(params[:id]).updateToAdmin()
redirect_to admin_list_path, info: "The user with an ID of #{idToToggle} has had their admin attribute toggled!"
end
end
结束
我想做的不是在切换管理员时重新加载页面,而是使用一些 javascript 重写 dom 的那部分。
解决此问题的更好方法是什么?
这里只是我已经尝试过的各种资源中的一小部分。
- How to call a controller's method from a view?
- Can we call a Controller's method from a view (as we call from helper ideally)?
- Call controller method with rails-Ajax?
- https://www.reddit.com/r/rails/comments/7iyp6g/want_a_button_to_call_a_method_apparently_this_is/
- How do I call a JavaScript function from an html.erb
感谢您的帮助。
--- 编辑以获取更多信息。
使用干净的 Rails 应用程序,我现在能够更干净地调用 Controller 方法,但我没有收到 ajax 请求来更新页面以显示操作已完成。 (我期待 bool 值变化和闪光灯)。以下是相关代码:
用户.js
$("#edit-form").html("<%= j render partial: 'form', locals: { user: @user } %>")
_form.html.erb
<%= form_for user do |form| %>
<%= user.admin %>
<% end %>
<%= link_to "Toggle Admin", toggle_admin_user_path(user), method: :put, remote: true %>
编辑.html.erb
<h1>Editing User</h1>
<div id="edit-form">
<%= render partial: 'form', locals: { user: @user } %>
</div>
<%= link_to 'Show', @user %> |
<%= link_to 'Back', users_path %>
users_controller.rb 请注意,我只包括了 toggle_admin
和其他一些方法,其余的只是脚手架。
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy, :toggle_admin]
def toggle_admin
if 1 == 1
logger.info "This is from info"
u = User.find(params[:id])
u.admin = !(u.admin)
u.save
respond_to do |format|
format.js { flash[:info] = "The user with an ID of #{@user.id} has had their admin attribute toggled!" }
end
else
redirect_to admin_list_path, danger: "You tried to make yourself a normal user! Don't do that!"
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
@user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.fetch(:user, {})
end
end
最佳答案
路由
首先,如果您需要资源中的嵌套自定义路由,您可以将其定义为该资源的成员:
resources :users do
put 'toggle_admin', on: :member
end
返回:
toggle_admin PUT /users/:id/toggle(.:format) users#toggle
其次,您的方法名称应该在 snake_case 中:def toggle_admin
See "Instance Methods" section
Controller
如果你只是想更新一个用户为管理员(通过这里的这个方法猜测:User.find(params[:id]).updateToAdmin()
),你可以定义自定义的toggle_admin
UsersController
中的方法。
你自定义的触发ajax请求的方法应该响应js格式并指向对应的js View (toggle_admin.js.erb
)
作为资源 User
的成员,您可以将其添加到 before_action
回调中,以便在调用该方法时返回正确的用户。
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy, :toggle_admin]
#...
def toggle_admin
if #some condition
# do some logic here
respond_to do |format|
format.js { flash[:info] = "The user with an ID of #{@user.id} has had their admin attribute toggled!" }
end
else
redirect_to admin_list_path, danger: "You tried to make yourself a normal user! Don't do that!"
end
end
end
View
在rails views中,当你想使用ajax更新一个 View 而不用reload时,你需要使用partial。这是将在特定 DOM 元素上的 .js.erb
文件中刷新的部分。
让我们为用户#edit View 做一个例子。
首先,您需要在部分 form
中呈现 View ,并将其包装到具有特定 id
的 div 中:
edit.html.erb
<div id="edit-form">
<%= render partial: 'form', locals: { user: @user } %>
</div>
局部:
_form.html.erb
<%= form_for user do |form| %>
# the form
<% end %>
<%= link_to "Toggle Admin", toggle_admin_user_path(user), method: :put, remote: true %>
# don't forget the remote: true for the ajax call
最后是自定义操作的 .js.erb
(假设您有 jquery):
toggle_admin.js.erb
$("#edit-form").html("<%= j render partial: 'form', locals: { user: @user } %>")
瞧!单击链接时,您可以使用来自 Controller 的新信息刷新编辑 View ,而无需重新加载 View 。
当然,这是经典资源编辑 View 的示例,但您可以根据任何情况对其进行调整。只需在路由、 Controller 、 Controller 方法和 View (AdminController、 ListView 等...)之间保持良好的命名即可
编辑
要处理 flash 消息,您需要在布局中添加 > application.html.erb :
<body>
<% flash.each do |key, value| %>
<%= content_tag :div, value, class: "classname" %>
<% end %>
<%= yield %>
</body>
关于javascript - Rails AJAX 请求 Controller 方法,然后调用 javascript 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50300962/