Rails 5:使用 AJAX 编辑索引上的用户角色

Posted

技术标签:

【中文标题】Rails 5:使用 AJAX 编辑索引上的用户角色【英文标题】:Rails 5: edit user role on index with AJAX 【发布时间】:2016-11-01 20:10:59 【问题描述】:

我正在尝试创建可以从下拉列表中选择用户的视图,然后加载特定用户角色编辑的角色部分下方。

这就是我在 /roles/index.html.erb

中的内容
<div class="form-group">
  <label class="col-sm-2 control-label">User name</label>
    <div class="col-sm-10"><select class="form-control m-b" name="users" id="user_list">
     <option value="">Please, select user</option>
      <% @users.each do |user| %>
       <% for role in user.roles %>
        <option value="<%= role.id %>" data-edit-url="<%= edit_common_role_path(role.id) %>"><%= user.name %></option>
       <% end %>
      <% end %>
    </select>
  </div>
</div>

/roles_controller.rb 我有这个:

def index #Here users belonging to current_user is found
 @users = User.joins(:accounts).where("accounts.company_id IN (?)",
          current_user.companies.pluck(:id)).distinct
end

def edit #Each user has its role with user_id column
 @role = Role.find(params[:id])
end

我是编码新手,已经阅读了很多相关的博客,但是 我不知道如何使用下拉列表和 AJAX 在单一视图中执行此操作?我将不胜感激,谢谢.

更新

此 JS 可以打开特定选定的用户角色进行编辑:

<script type="text/javascript">
      edit = $('#user_list').change(function() 
      window.location = $(this).find(":selected").data('edit-url');
     );
</script>

更新 2

/roles/index.html.erb 中,我添加了将加载角色详细信息的部分:

<div id = selected_role >
  <%= render 'common/roles/editrole' %>
</div>

特定的编辑视图部分以此开头

<%= form_for([:common, @role]) do |f| %>

目前我收到错误:First argument in form cannot contain nil or be empty

问题似乎在于,在索引视图中,它尝试渲染部分编辑以寻找某些角色,但是此时没有选择任何用户(角色 ID 为空)。请问如何解决这个问题?


编辑表单的解决方案

感谢@Ahmad hamza 和@Jeff,我来到了这个解决方案,我可以在其中执行编辑操作,但仍需要对更新操作进行最后的润色。

/common/roles/index.erb 我有这个:

<form class="form-horizontal" role="form" method="get" action="/common/roles" data-remote="true">
<div class="col-sm-10"><select class="form-control m-b" name="users" id="user_list">
  <option value="">Please, select user</option>
     <% @users.each do |user| %>
        <% for role in user.roles %>
           <option value="<%= role.id %>"><%= user.name %></option>
        <% end %>
     <% end %>
  </select>
</div>
<!-- Here we render role edit form -->
  <div id = 'selected_role' ></div>
<!-- Role edit form ends -->

这是选择显示用户名的位置,角色 ID 是选项值。

roles.js 我有监听器,其中选择角色 ID 传递给编辑:

(function($) 
$('#user_list').change(function() 
  var roleId = $( "#user_list" ).val();
  $.ajax(
    url: '/common/roles/' + roleId + '/edit',
    method: 'GET',
  );
);
)(jQuery); /*global jQuery*/

/common/roles/edit.js.erb 看起来像这样:

$("#selected_role").html("<%=j render 'common/roles/editrole', locals:  role: @role  %>");

它呈现角色编辑部分/common/roles/_editrole.html.erb

<%= form_for :role, method: :patch, remote: true do |f| %>
<form class="m-t" role="form" action="" id="editrole">
        <div class="form-group">
            <label class="col-sm-2 control-label">General</label>
            <div class="col-sm-10" >
           <%= f.select :general, Role.generals.to_a.map  |w| [w[0].humanize, w[0]] , , class:"form-control m-b" %>
            </div>
        </div>
   <%= f.submit "Save changes", class: "btn btn-primary block full-width m-b" %>
  <% end %>
</form>

要完成此表格,我仍然需要完成有问题的更新操作。在提交角色编辑表单时,它会停留在编辑操作中,并在控制台中显示此错误:

ActionController::RoutingError (No route matches [PATCH] "/common/roles/1/edit"):

虽然有特定的路线:

common_role PATCH  /common/roles/:id(.:format)     common/roles#update

/common/roles_controller.rb 我有这个:

def update
@role = Role.find(params[:id])
if @role.update_attributes(role_params)
  format.html 
              flash[:success] = "Role updated!"
              redirect_to common_roles_path
  
  format.js

/common/roles/update.js.erb 我有这行:$('.editrole').hide()

请问如何解决此更新操作问题?

【问题讨论】:

如果我做对了,那么当从下拉列表中选择用户时,它应该加载该用户的角色。对吗? 好的,所以我的建议是——先弄清楚你在没有 AJAX 的情况下如何做(你当前的表单不会这样做——它选择一个角色,而不是一个用户)......然后一旦你明白了,就把它转换成 AJAX。 在下拉列表中添加一个 on change javascript 监听器。通过 ajax 发布到 API,该 API 将在 json 中返回用户的角色。使用 jquery 将 json 渲染到页面上。 @Ahmad hamza 是的,你是对的。在视觉上我显示用户名,但值是特定的用户角色 ID。 你想在哪里显示用户的角色? 【参考方案1】:

正如您所说,您希望在从下拉列表中选择用户时显示用户的角色。

步骤

    在资产文件夹中创建一个js文件,并将其也包含在manifest文件中(application.js)

    触发dropdownfunction onChange 并使用id 属性从下拉列表中获取选定的user

    $( ".m-b" ).change(function() 
      var roleId = $( "#user_list" ).val();
    );
    

    这里ajax 出现在图片中,这将有助于将所选userrole_idview 发送到controller,作为回报,它将返回角色的object

    $( ".m-b" ).change(function() 
      var roleId = $( "#user_list" ).val();
      $.ajax(
        url: 'roles/' + roleId + '',  #roles edit path
        method: 'GET',
        data: 
          id: roleId;
        
      );
    );
    

    roles 控制器的edit 动作中:

    def edit
      @role = Role.find(params[:id])
      respond_to do |format|
        format.html
        format.js  @role   # format.js will identify the ajax request
      end
    end
    

    rolesindex 页面中添加div,您将在其中呈现找到的角色对象的详细信息。

    现在您需要更新您的 ajax 请求方法,以便它将响应附加到 div 中。

    $( ".m-b" ).change(function() 
      var roleId = $( "#user_list" ).val();
      $.ajax(
        url: 'roles/' + roleId + '',  #roles edit path
        method: 'GET',
        data: 
          id: roleId;
        
      )
      .done(function( response ) 
         $('#selected_role').append(response);
      );
    );
    

    希望这会有所帮助。

【讨论】:

谢谢!当我添加部分编辑视图时,我似乎遇到了错误。请您看一下上面的更新 2 吗? format.js @role 是什么意思?或者具体来说,@role 是否作为 json 对象传递?如果是这样,你为什么不直接使用format.json status: 'success', role: @role.to_json @Jeff 你能看看我在上面的 Update2 中遇到的错误吗?我在/roles/index.html.erb 做错了什么? 首先&lt;div id = selected_role &gt; 应该是&lt;div id ='selected_role' &gt;。在控制器中的edit 操作中,您应该执行@role ||= Role.new @Jeff 谢谢,但是它一直给我同样的错误 + 对于你关于format.json 的建议,它给出了意外':'的语法错误

以上是关于Rails 5:使用 AJAX 编辑索引上的用户角色的主要内容,如果未能解决你的问题,请参考以下文章

Rails 3.1 ajax:成功处理

无法在 Rails 5 中将 Json 数据获取到 Ajax

Rails 5 - Ajax 刷新后重新初始化 Javascript?

编辑值时输入失去焦点。使用 ngFor 和 ngModel。角5

Rails:参数太少

Rails 可以让 Ajax 保持开放多久