I have mulitple divs that are dipslayed using a foreach loop and i want to be able re-order using 2 buttons and i also want be able to save this order so when i come back on after refreshing the page the new order is still present.
**What I have done so far **
I have managed to use JavaScript to move the html elements up and down using 2 buttons. I have also added public int OrderNum to the public class Lesson and I have made the divs order by increasing OrderNum. However i'm struggling to be able to change the orderNumm when the button is of each div when the buttons are pressed.
C#
public class Lesson : IModel
{
public override String partitionKey { get => CourseId; }
[Required]
public string CourseId { get; set; }
[Required]
[StringLength(256, ErrorMessage = "Maximum {1} characters")]
public string Title { get; set; }
[Required]
public string Content { get; set; }
public string ImageID { get; set; }
public string ImageURL { get => (ImageID != null) ? Storage.Image.Path(ImageID) : null; }
public int OrderNum { get; set; }
}
HTML
@foreach (var Lesson in Model.Lessons.OrderBy(x => x.OrderNum))
{
<li >
<a href="@Url.Action("Index","Lesson", new { CourseCategory = Model.Course.Category, CourseID = Model.Course.id, Lesson.id })">@Lesson.OrderNum</a>
@if (AppUser.CurrentUser.Areas.Admin)
{
<a class='up' href='#'><i ></i></a> <a class='down' href='#'><i ></i></a>
<div >
<div>
<a href="@Url.Action("EditLesson", "Lesson", new { CourseCategory = Model.Course.Category, CourseID = Model.Course.id, Lesson.id })">
<i ></i>
</a>
</div>
<div>
<form action="@Url.Action("DeleteLesson","Lesson", new{CourseCategory = Model.Course.Category, CourseID = Model.Course.id, Lesson.id})" method="post">
<button type="submit" value="Delete"></button>
</form>
</div>
</div>
}
</li>
}
JavaScript
window.onload = function () {
var upLink = document.querySelectorAll(".up");
for (var i = 0; i < upLink.length; i ) {
upLink[i].addEventListener('click', function () {
var wrapper = this.parentElement;
if (wrapper.previousElementSibling)
wrapper.parentNode.insertBefore(wrapper, wrapper.previousElementSibling);
});
}
var downLink = document.querySelectorAll(".down");
for (var i = 0; i < downLink.length; i ) {
downLink[i].addEventListener('click', function () {
var wrapper = this.parentElement;
if (wrapper.nextElementSibling)
wrapper.parentNode.insertBefore(wrapper.nextElementSibling, wrapper);
});
}
CodePudding user response:
I have not tested the upcoming codes, just to create an insight: First: Add an attribute to each "list-group-item" element to you can relate them to the server object in future.
<li data-elementid="@Lesson.id">
Then at click event handlers post new orders to the server to be set to the objects:
upLink[i].addEventListener('click', function () {
var wrapper = this.parentElement;
if (wrapper.previousElementSibling)
wrapper.parentNode.insertBefore(wrapper, wrapper.previousElementSibling);
var elements= document.querySelectorAll(".list-group-item");
var stringToBeSend='';
for (var j = 0; j < elements.length; j ) {
stringToBeSend =elements[j].getAttribute("data-elementid") ":" j ",";
}
fetch('[Address to a new controller to save new positions. e.g. /api/lessons/UpdatePositions]', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: stringToBeSend})
.catch(error => console.error('Unable to post positions.', error));
});
Now you need a controller to get the comma separated string and update new lesson positions. For example:
[HttpPost("UpdatePositions")]
public IActionResult UpdatePositions(string commaSepPositions)
{
var valueLists = commaSepPositions.Split(',');
foreach(var value in valueLists)
{
if (!string.IsNullOrWhiteSpace(value))
{
var positions = value.Split(':');
if (positions.Length > 1)
{
var lessonIDStr = positions[0];
var newPositionStr = positions[1];
}
//Now update entity in db
}
}
return Ok();
}