I have two lists (list-left and list-right) prepared and populate. Then I have this JS code to move elements from one list to another. And it works fine.
$(function () {
$('body').on('click', '.list-group .list-group-item', function () {
$(this).toggleClass('active');
});
$('.list-arrows button').click(function () {
var $button = $(this), actives = '';
if ($button.hasClass('move-left')) {
actives = $('.list-right ul li.active');
actives.clone().appendTo('.list-left ul');
actives.remove();
} else if ($button.hasClass('move-right')) {
actives = $('.list-left ul li.active');
actives.clone().appendTo('.list-right ul');
actives.remove();
}
});
});
But honestly I don't know how to pass the result back to codebehind when user clicks the submit button on the form?
This is my cshtml code:
@using AuthDatabase.Entities
@using Identity.Models
@model RoleEdit
@{
ViewData["Title"] = "Edit role";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>@ViewData["Title"]</h1>
<br />
<h4>Roles</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<form method="post">
<input type="hidden" name="roleName" value="@Model.Role.Name" />
<input type="hidden" name="roleId" value="@Model.Role.Id" />
<div class="row">
<div class="dual-list list-left col-md-5">
<h5>No roles</h5>
<div class="well text-right">
<div class="row">
<div class="col-md-10">
<div class="input-group">
<span class="input-group-addon glyphicon glyphicon-search"></span>
<input type="text" name="SearchDualList" class="form-control" placeholder="search" />
</div>
</div>
</div>
<ul class="list-group">
@foreach (AppUser user in Model.NonMembers)
{
<li class="list-group-item">@user.UserName</li>
}
</ul>
</div>
</div>
<div class="list-arrows col-md-1 text-center">
<button class="btn btn-default btn-sm move-left" type="button">
<span class="btn btn-primary"><</span>
</button>
<button class="btn btn-default btn-sm move-right" type="button">
<span class="btn btn-primary">></span>
</button>
</div>
<div class="dual-list list-right col-md-5">
<h5>With roles</h5>
<div class="well">
<div class="row">
<div class="col-md-10">
<div class="input-group">
<input type="text" name="SearchDualList" class="form-control" placeholder="search" />
<span class="input-group-addon glyphicon glyphicon-search"></span>
</div>
</div>
</div>
<ul class="list-group">
@foreach (AppUser user in Model.Members)
{
<li class="list-group-item">@user.UserName</li>
}
</ul>
</div>
</div>
</div>
<br />
<a asp-action="Index" class="btn btn-secondary">Back to List</a>
<button type="submit" class="btn btn-primary">Save</button>
</form>
@section Scripts
{
<script src="~/js/lists.js" asp-append-version="true"></script>
}
And my controller:
public async Task<IActionResult> Edit(string id)
{
IdentityRole role = await _roleManager.FindByIdAsync(id);
List<AppUser> members = new List<AppUser>();
List<AppUser> nonMembers = new List<AppUser>();
foreach (AppUser user in _userManager.Users)
{
var list = await _userManager.IsInRoleAsync(user, role.Name) ? members : nonMembers;
list.Add(user);
}
return View(new RoleEdit
{
Role = role,
Members = members,
NonMembers = nonMembers
});
}
[HttpPost]
public async Task<IActionResult> Edit(RoleModification model)
{
IdentityResult result;
if (ModelState.IsValid)
{
foreach (string userId in model.AddIds ?? new string[] { })
{
AppUser user = await _userManager.FindByIdAsync(userId);
if (user != null)
{
result = await _userManager.AddToRoleAsync(user, model.RoleName);
if (!result.Succeeded)
Errors(result);
}
}
foreach (string userId in model.DeleteIds ?? new string[] { })
{
AppUser user = await _userManager.FindByIdAsync(userId);
if (user != null)
{
result = await _userManager.RemoveFromRoleAsync(user, model.RoleName);
if (!result.Succeeded)
Errors(result);
}
}
}
if (ModelState.IsValid)
return RedirectToAction(nameof(Index));
else
return await Edit(model.RoleId);
}
The [HttpPost] Edit action requires RoleModification object with two arrays of strings (changes on the lists -> it is now based on previous solution without jquery). It would be also suitable to have only one list-right passed.
public class RoleModification
{
[Required]
public string RoleName { get; set; }
public string RoleId { get; set; }
public string[] AddIds { get; set; }
public string[] DeleteIds { get; set; }
}