Django Flashing/Flickering on each Render on CRUD function [closed] - javascript

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I'm working on a Django REST Framework task. Every time I perform a Create, Retrieve, Update, and Delete function the list item of div is flashing every time.
How can I stop this flashing/flickering?
From API URL I have to display the paginated data. If I click the next page then also flickering is occurred. How can I get rid of this flickering/flashing issue?
main.html
{% extends 'todo/index.html' %}
{% block content %}
<div class="center-column" id="center-column">
<h5 class="card-title" id="welcome" data-id={{ request.user.id }}>
Hello {{ request.user.username }}, Create your todo list
</h5>
<div id="addTodoForm">
<form action="" method="">
<div class="input-group-append">
<input type="text" class="title-input" required name="title" placeholder="e.g. Chemistry">
<button type="submit" class="form-control btn btn-primary mr-sm-2" id="addTodobtn">
Add Todo
</button>
</div>
</form>
</div>
</div>
<div class="row" id="row">
<div class="col-sm-5">
<div class="card">
<div class="card-body">
<h5 class="card-title">
Incomplete Todo Items
</h5>
<hr />
<div class="list-group" id="incompleteTodo">
</div>
<hr>
<nav aria-label="..." id="incompletePagination">
<ul class="pagination justify-content-center">
<li class="page-item">
<button class="page-link" tabindex="-1" id="prevPageI">&laquo</button>
</li>
<li class="page-item"><button class="page-link" id="currPageI">1</button></li>
<li class="page-item"><button class="page-link" id="nextPageI">&raquo</button></li>
</ul>
</nav>
</div>
</div>
</div>
<div class="col-sm-5">
<div class="card">
<div class="card-body">
<h5 class="card-title">
Completed Todo Items
</h5>
<hr>
<div class="list-group" id="completedTodo">
</div>
<hr>
<nav aria-label="..." id="completedPagination">
<ul class="pagination justify-content-center">
<li class="page-item">
<button class="page-link" tabindex="-1" id="prevPageC">&laquo</button>
</li>
<li class="page-item"><button class="page-link" id="currPageC">1</button></li>
<li class="page-item"><button class="page-link" id="nextPageC">&raquo</button></li>
</ul>
</nav>
</div>
</div>
</div>
</div>
{% endblock %}
main.js
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let todo = 0; todo < cookies.length; todo++) {
const cookie = cookies[todo].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function taskStatus(item) {
return `
${item.map(task =>
`
<div class="card list-group-item list-group-item-danger mt-1" id="task_${task.id}">
<span class="font-italic">${task.heading}</span>
<div class="float-right">
<badge type="submit" class="badge badge-light" id="complete-task_${task.id}">
✔
</badge>
<badge type="submit" class="badge badge-warning ml-1" id="delete-task_${task.id}">
❌
</badge>
</div>
<div class="float-right">
<badge type="submit"
class="badge badge-dark mr-1 edit-task"
id="edit-task_${task.id}"
data-target="#updateTaskModal_${task.id}"
data-toggle="modal">
edit
</badge>
<div class="modal fade" id="updateTaskModal_${task.id}" tabindex="-1" role="dialog"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Update Todo</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="list-group-item list-group-item-warning">
<input type="text" required id='updateTaskInp_${task.id}' size='45'
name="heading_${task.id}" value="${task.heading}">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="updateTaskModalSubmit_${task.id}"
data-dismiss="modal">
Submit
</button>
</div>
</div>
</div>
</div>
</div>
</div>`
).join('')}
`
};
function taskCompleted(item) {
return `
${item.map(task =>
`
<div class="list-group-item bg-danger mb-1">
<span class="text-light font-italic">${task.heading}</span>
<div class="float-right">
<badge type="submit" class="badge badge-warning ml-1" id="delete-task_${task.id}">
❌
</badge>
</div>
</div>
`
).join('')}
`
};
$(document).ready(function() {
const incompleteHome = '/api/todo-incomplete/?incomplete=1';
const completedHome = '/api/todo-completed/?completed=1';
todoIncompleteItems(incompleteHome);
todoCompletedItems(completedHome);
// Create Todo Item
$('#addTodobtn').click(function(e) {
e.preventDefault();
var title = $(".title-input").val();
var user_id = $('#welcome').data('id');
console.log("Title: ", title)
$.ajax({
url: "api/create-todo/",
type: "POST",
headers:{
"X-CSRFToken":csrftoken
},
data: {
"title": title,
"user_id": user_id,
},
success: function(data) {
$("#incompleteTodo").html('');
todoIncompleteItems(incompleteHome);
},
error: function(err) {
alert("check the console for errors");
console.log("Create Todo Item Error: ", err)
}
})
$(".title-input").val('');
})
var nextIncomplete = null;
var prevIncomplete = null;
var currentPageIncomplete = null;
var currentIncomplete = null;
$('#nextPageI').click(function() {
currentIncomplete +=1
$('#currPageI').html(currentIncomplete)
todoIncompleteItems(nextIncomplete);
})
$('#prevPageI').click(function() {
currentIncomplete -= 1
$('#currPageI').html(currentIncomplete)
todoIncompleteItems(prevIncomplete);
})
// Page wise Incomplete Todo Items
function todoIncompleteItems(incompleteUrl) {
$('#incompleteTodo').html('');
$.ajax({
url: incompleteUrl,
type: 'GET',
success: function(data) {
currentPageIncomplete = `api/todo-incomplete/?incomplete=${data.current_page_no}`;
currentIncomplete = data.current_page_no;
nextIncomplete = data.next;
if (data.next != null) {
$('#nextPageI').css("visibility", "visible")
} else {
$('#nextPageI').css("visibility", "hidden")
}
prevIncomplete = data.previous;
if (data.previous != null) {
$('#prevPageI').css("visibility", "visible")
} else {
$('#prevPageI').css("visibility", "hidden")
}
if (data.next === null && data.previous === null) {
$('#incompletePagination').css("visibility", "hidden")
} else {
$('#incompletePagination').css("visibility", "vidible")
}
let todoItems = data.results;
for (let todo in todoItems) {
$('#incompleteTodo').append(
`<div class="list-group-item list-group-item-primary mb-1" id="todo-${todo}"
data-id="${todoItems[todo].id}">
<span class="font-weight-bold">${todoItems[todo].title}</span>
<div class="float-right">
<badge type="submit" class="badge badge-warning" id="deleteTodo_${todoItems[todo].id}">
❌
</badge>
</div>
<div class="float-right">
<badge type="submit" class="badge badge-light mr-1"
id="completed-todo_${todoItems[todo].id}">
✔
</badge>
</div>
<div class="float-right">
<badge type="submit" class="badge badge-dark mr-1 edit"
data-target="#updateTodoModal_${todoItems[todo].id}" data-toggle="modal">
edit
</badge>
<div class="modal" id="updateTodoModal_${todoItems[todo].id}" tabindex="-1"
role="dialog" aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Update Todo</h5>
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="list-group-item list-group-item-warning">
<input type="text" id='updateTodoInp_${todoItems[todo].id}'
size="45" value="${todoItems[todo].title}">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">
Close
</button>
<button type="button" class="btn btn-primary"
id="updateModalSubmit_${todoItems[todo].id}" data-dismiss="modal">
Submit
</button>
</div>
</div>
</div>
</div>
</div>
<div class="float-right mr-1">
<badge type="submit" class="badge badge-primary add-task" data-toggle="modal"
data-target="#addTaskModal_${todoItems[todo].id}">
✚
</badge>
<div class="modal" id="addTaskModal_${todoItems[todo].id}" tabindex="-1" role="dialog"
aria-labelledby="taskModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="taskModalLabel">
Add New Task for ${todoItems[todo].title}
</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="list-group-item list-group-item-dark">
<input type="text" required id='addTaskInp_${todoItems[todo].id}' size="45"
name="heading" placeholder="Enter the task name here...">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary closeModal"
data-dismiss="modal">
Close
</button>
<button type="button" class="btn btn-primary"
id="taskSubmit_${todoItems[todo].id}" data-dismiss="modal">
Submit
</button>
</div>
</div>
</div>
</div>
</div>
<div class="mt-3 incompleteTodo-task">
${todoItems[todo].tasks ? taskStatus(todoItems[todo].tasks) : ''}
</div>
</div>
`
)
};
for (var todo in todoItems) {
var deleteTodoBtn = document.querySelector(`#deleteTodo_${todoItems[todo].id}`)
var taskSubmitBtn = document.querySelector(`#taskSubmit_${todoItems[todo].id}`)
var editTodoBtn = document.querySelector(`#updateModalSubmit_${todoItems[todo].id}`)
var completedTodoBtn = document.querySelector(`#completed-todo_${todoItems[todo].id}`)
deleteTodoBtn.addEventListener('click', (function(element) {
return function() {
deleteTodo(element)
}
})(todoItems[todo]))
taskSubmitBtn.addEventListener('click', (function(element) {
return function() {
addTaskItem(element)
}
})(todoItems[todo]))
editTodoBtn.addEventListener('click', (function(element) {
return function() {
editTodoItem(element)
}
})(todoItems[todo]))
completedTodoBtn.addEventListener('click', (function(element) {
return function() {
completedTodo(element)
}
})(todoItems[todo]))
var taskItems = todoItems[todo].tasks
for (var task in taskItems) {
var deleteTaskBtn = document.querySelector(`#delete-task_${taskItems[task].id}`)
var completeTaskBtn = document.querySelector(`#complete-task_${taskItems[task].id}`)
var editTaskBtn = document.querySelector(`#updateTaskModalSubmit_${taskItems[task].id}`)
deleteTaskBtn.addEventListener('click', (function(element) {
return function() {
deleteTask(element)
}
})(taskItems[task]))
completeTaskBtn.addEventListener('click', (function(element) {
return function() {
completedTask(element)
}
})(taskItems[task]))
editTaskBtn.addEventListener('click', (function(element) {
return function() {
editTaskItem(element)
}
})(taskItems[task]))
if(taskItems[task].completed === true) {
$(`#task_${taskItems[task].id}`).removeClass("list-group-item-danger")
$(`#task_${taskItems[task].id}`).addClass("list-group-item-dark")
$(`#edit-task_${taskItems[task].id}`).remove()
$(`#complete-task_${taskItems[task].id}`).remove()
}
}
}
},
error: function(err) {
console.log(err)
}
});
}
var nextCompleted = null;
var prevCompleted = null;
var currentPageCompleted = null;
var currentCompleted = null;
$('#nextPageC').click(function() {
currentCompleted +=1
$('#currPageC').html(currentCompleted)
todoCompletedItems(nextCompleted);
})
$('#prevPageC').click(function() {
currentCompleted -=1
$('#currPageC').html(currentCompleted)
todoCompletedItems(prevCompleted);
})
// Page wise Completed Todo Items
function todoCompletedItems(CompletedUrl) {
$('#completedTodo').html('');
$.ajax({
url: CompletedUrl,
type: 'GET',
success: function(data) {
var todoItems = data.results;
currentPageCompleted = `api/todo-completed/?completed=${data.current_page_no}`
currentCompleted = data.current_page_no
nextCompleted = data.next;
if (data.next != null) {
$('#nextPageC').css("visibility", "visible")
} else {
$('#nextPageC').css("visibility", "hidden")
}
prevCompleted = data.previous;
if (data.previous != null) {
$('#prevPageC').css("visibility", "visible")
} else {
$('#prevPageC').css("visibility", "hidden")
}
if (data.next === null && data.previous === null) {
$('#completedPagination').css("visibility", "hidden")
} else {
$('#completedPagination').css("visibility", "visible")
}
for (var todo in todoItems) {
$('#completedTodo').append(
`
<div class="list-group-item bg-success mb-1"
id="todo_${todoItems[todo].id}" data-id="${todoItems[todo].id}">
<span class="text-light font-weight-bold">${todoItems[todo].title}</span>
<div class="float-right">
<badge type="submit" class="badge badge-warning mr-2"
id="deleteTodo_${todoItems[todo].id}">
❌
</badge>
</div>
<div class="completedTodoTask mt-3">
${todoItems[todo].tasks ? taskCompleted(todoItems[todo].tasks) : ''}
</div>
</div>
`
)
}
for (var todo in todoItems) {
var deleteTodoBtn = document.getElementById(`deleteTodo_${todoItems[todo].id}`)
deleteTodoBtn.addEventListener('click', (function(item) {
return function() {
deleteTodo(item)
}
})(todoItems[todo]))
var taskItems = todoItems[todo].tasks
for (var task in taskItems) {
var deleteTaskBtn = document.getElementById(`delete-task_${taskItems[task].id}`)
deleteTaskBtn.addEventListener('click', (function(element) {
return function() {
deleteTask(element)
}
})(taskItems[task]))
}
}
},
error: function(err) {
console.log(err);
}
})
}
function editTodoItem(item) {
var user_id = $('#welcome').data('id');
var title = $(`#updateTodoInp_${item.id}`).val();
$.ajax({
url: `api/update-todo/${item.id}/`,
type: 'POST',
headers:{
"X-CSRFToken":csrftoken
},
data: {
'title': title,
'user_id': user_id,
},
success: function(data) {
todoIncompleteItems(currentPageIncomplete);
},
error: function(data) {
alert("check the console for errors")
console.log('Problem in updating todo item: ', data)
}
})
}
function addTaskItem(item) {
var heading = $(`#addTaskInp_${item.id}`).val();
var user_id = $('#welcome').data('id')
$.ajax({
url: 'api/create-task/',
type: 'POST',
data: {
'heading': heading,
'user': user_id,
'todo': item.id,
'csrfmiddlewaretoken': csrftoken,
},
success: function(data) {
todoIncompleteItems(currentPageIncomplete);
},
error: function(data) {
alert("check the console for errors")
console.log('Problem in adding new task item: ', data)
}
})
}
function completedTodo(item) {
var user_id = $('#welcome').data('id')
$.ajax({
url: `api/completeTodoTask/${item.id}/`,
type: 'POST',
headers:{
"X-CSRFToken":csrftoken
},
data: {
'title': item.title,
'user_id': user_id,
'completed': true,
},
success: function(data) {
todoIncompleteItems(currentPageIncomplete);
todoCompletedItems(completedHome);
},
error: function(data) {
alert("check the console for errors")
console.log('Problem in Completing Todo item: ', data)
}
})
}
function deleteTodo(item) {
$.ajax({
url: `api/delete-todo/${item.id}/`,
type: 'DELETE',
headers: {
"X-CSRFToken": csrftoken,
},
success: function(data) {
todoIncompleteItems(currentPageIncomplete);
todoCompletedItems(currentPageCompleted);
},
error: function(data) {
alert("check the console for errors")
console.log("There was an error while deleting Todo Item: ", data)
}
})
}
function editTaskItem(item) {
var user_id = $('#welcome').data('id');
var heading = $(`#updateTaskInp_${item.id}`).val();
$.ajax({
url: `api/update-task/${item.id}/`,
type: 'POST',
headers:{
"X-CSRFToken":csrftoken
},
data: {
'heading': heading,
'user': user_id,
'todo': item.todo,
},
success: function(data) {
todoIncompleteItems(currentPageIncomplete);
},
error: function(err) {
alert("check the console for errors")
console.log("There was an error while deleting Task Item: ", data)
}
})
}
function completedTask(item) {
var user_id = $('#welcome').data('id')
$.ajax({
url: `api/complete-task/${item.id}/`,
type: 'POST',
data: {
'heading': item.heading,
'user': user_id,
'completed': true,
'title': 'title',
'user_id': user_id,
'csrfmiddlewaretoken': csrftoken,
},
success: function(data) {
todoIncompleteItems(currentPageIncomplete);
todoCompletedItems(completedHome);
},
error: function(data) {
console.log('Problem in Completing Task item: ', data)
}
})
}
function deleteTask(item) {
console.log("Delete Task Button Clicked: ", item.heading)
$.ajax({
url: `api/delete-task/${item.id}/`,
type: 'DELETE',
headers: {
"X-CSRFToken": csrftoken,
},
success: function(data) {
todoIncompleteItems(currentPageIncomplete);
todoCompletedItems(currentPageCompleted);
},
error: function(data) {
alert("check the console for errors")
console.log("There was an error while deleting Task Item: ", data)
}
})
}
})

At first, I have removed $("#incompleteTodo").html("") from the main.js file.
Then, Created let todo_incomplete = []; outside the function for storing the data
locally and add ed
let todoItems = data.results;
for (let todo in todoItems) {
try {
document.getElementById(`todo_${todo}`).remove();
} catch(err){}
}
After the loop ends, I have added
if(todo_incomplete.length > todoItems.length){
for (var i = todoItems.length; i < todo_incomplete.length; i++){
document.getElementById(`todo_${i}`).remove();
}
}
todo_incomplete = todoItems;
I used this method and it's working fine. I haven't found any solutions for this.
On implementing the same method for completed_Items I was able to achieve on bot the list's.
You can check this YouTube video, timestamp 49:00

Related

Getting button Id and passing id to a model button id

I have a dynamic button, that has an attribute of Stepid. What i am trying to do
is capture that attribute when the button is clicked and pass the same attribute into my model and assign the StepId value as my button Id in the modal.
My button
<button class="btn btn-warning moveRecipeStep" id="blah" data-bind="attr: {'data-id': StepId, data_recipe_name: $parent.RecipeName}" data-toggle="modal" data-target="#moveRecipeReason">#Html.LocalisedStringFor(model => model.MoveToStageText)</button>
and my modal
<section id="hidden">
<div class="modal fade" id="moveReason" tabindex="-1" role="dialog" arial-labelledby="moveReasonLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="moveReasonLabel">What is the reason for the Step move?</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body reasonDialog">
<form>
<div class="form-group">
#Html.LabelFor(model => model.ReasonText)
#Html.TextAreaFor(model => model.ReasonText, new { rows = 4, #class = "form-control", maxlength = "100", data_bind = "value: Reason" })
</div>
</form>
</div>
<div class="modal-footer">
<button id="DoMove" type="button" class="btn btn-primary">#Html.LocalisedStringFor(model => model.SubmitText)</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="moveRecipeReason" tabindex="-1" role="dialog" arial-labelledby="moveReasonLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="moveReasonLabel">What is the reason for the Recipe move?</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body reasonDialog">
<form>
<div class="form-group">
#Html.LabelFor(model => model.ReasonText)
#Html.TextAreaFor(model => model.ReasonText, new { rows = 4, #class = "form-control", maxlength = "100", data_bind = "value: Reason" , id = "blah" })
</div>
</form>
</div>
<div class="modal-footer">
<button id="DoMoveRecipe" type="button" class="btn btn-primary">#Html.LocalisedStringFor(model => model.SubmitText)</button>
</div>
</div>
</div>
</div>
</section>
And my javascript
var input = $(this);
var buttonId = input.attr("id");
var id = input.data("id");
var url = buttonId === 'MoveNext' ? '#Url.Action("MakeNext")' : '#Url.Action("MoveRecipePosition")';
$("#moveReason").modal("toggle");
if (buttonId === "MoveNext") {
$.ajax(url,
{
data: {
"Id": id,
"Reason": $("#moveReason .reasonDialog textarea").val(),
},
cache: false,
method: "POST",
}).done(function(returnData) {
if (returnData) {
if (returnData.BrokenRule !== null) {
alert(returnData.BrokenRule.Message);
} else if (returnData.ProcessStep !== null) {
var bFound = false;
//Done like this because you can only move backwards. Originally the logic was fuller but, most things don't change now.
//The extra logic just hides everything past the active one
for (var pos = 0; pos < viewModel.Stages().length; pos++) {
if (bFound) {
viewModel.Stages()[pos].Id(-1);
viewModel.Stages()[pos].IsNext(false);
} else if (viewModel.Stages()[pos].Id() == returnData.ProcessStep.Id) {
viewModel.Stages()[pos].IsNext(returnData.ProcessStep.IsNext);
viewModel.Stages()[pos].BenchId(returnData.ProcessStep.BenchId);
viewModel.Stages()[pos].BenchName(returnData.ProcessStep.BenchName);
viewModel.Stages()[pos].IsTransacted(returnData.ProcessStep.IsTransacted);
viewModel.Stages()[pos].RecipeName(returnData.ProcessStep.RecipeName);
bFound = true;
}
}
}
}
}).fail(function(xhr) {
try {
console.log(xhr.statusText);
console.log(xhr.responseText);
alert(xhr.statusText + "\r\n" + xhr.responseText);
} catch (ex) {
console.log(ex);
alert(ex);
}
});
} else {
$.ajax(url,
{
data: {
"SerialNumber": viewModel.SerialNumber(),
"Message": $("#moveRecipeReason .reasonDialog textarea").val(),
"StepId": a
},
cache: false,
method: "POST"
}).done(function(returnData) {
if (returnData) {
if (returnData.BrokenRule !== null) {
alert(returnData.BrokenRule.Message);
} else if (returnData.recipePosition !== null) {
var bFound = false;
//Done like this because you can only move backwards. Originally the logic was fuller but, most things don't change now.
//The extra logic just hides everything past the active one
for (var pos = 0; pos < viewModel.Stages().length; pos++) {
if (viewModel.Stages()[pos].RecipeName() !==
returnData.recipePosition.RecipeName)
continue;
for (var innerPos = 0;
innerPos < viewModel.Stages()[pos].RecipeStages().length;
innerPos++) {
var recipeStage = viewModel.Stages()[pos].RecipeStages()[innerPos];
if (bFound) {
recipeStage.StepId(-1);
recipeStage.IsNext(false);
} else if (viewModel.Stages()[pos].Id() === returnData.ProcessStep.Id) {
recipeStage.StepId(-1);
recipeStage.IsNext(true);
bFound = true;
}
}
}
}
}
}).fail(function(xhr) {
try {
console.log(xhr.statusText);
console.log(xhr.responseText);
alert(xhr.statusText + "\r\n" + xhr.responseText);
} catch (ex) {
console.log(ex);
alert(ex);
}
});
}
})
});
If anyone can give me some guidance, that much be much appreciated. Thank you very much.
It can be done simpler, here's an universal concept: How do you handle multiple submit buttons in ASP.NET MVC Framework?
Simple approach:
multiple submit button, same name (let it be abcd), different value
inside .NET controllers postback function have a string name (so string abcd) input parameter, where you check the value

Viima JQuery Comments - GetUsers(Pinged users) displaying incorrectly in partialview

References
jquery comments
The jquery comments documentation
this issue in github
Attachments
comments-data.js is test data : Download here
jquery-comments.js creates the whole comments system: Download here
jquery-comments.min.js if you require it: Download here
Description
I have a view with a list of "articles" with a "read more" button on each "article" in the list. When I click on the read more button a modal opens up with a partial view with the jquery comments in it. However, when I search for the pinged users (using the # sign), the list of users don't show by the textarea, but instead higher up in the modal (far from the textarea).
Below is an image, then below that is my code. You will see at the bottom of the image I have put the '#' sign and the list of users is displayed on the top, it should be by the textarea. It also seems that when I click on the articles lower in the list, the higher the list of users display when I push the '#' sign:
MVC View
Below is the part populating the "Articles" from where the Modal is being called from:
#{
int iGroupNameId = 0;
int iTotalArticles = 0;
foreach (var groupItems in Model.ArticleGroups)
{
iTotalArticles = Model.ArticlesList.Where(x => x.fkiGroupNameId == groupItems.pkiKnowledgeSharingCenterGroupsId).Count();
if (iTotalArticles > 0)
{
<div style="background: linear-gradient(#B5012E, darkred); margin: 10px; padding: 10px; font-weight: bold; color: white; text-transform: uppercase;">#groupItems.GroupName</div><div class="container" style="width:100%">
#if (groupItems.pkiKnowledgeSharingCenterGroupsId != iGroupNameId)
{
foreach (var item in Model.ArticlesList.Where(x => x.fkiGroupNameId == groupItems.pkiKnowledgeSharingCenterGroupsId))
{
<div class="row">
<div class="col-md-4">
#if (User.IsInRole("Administrator"))
{
<div class="pull-right">
<div class="btn-group">
<button class="btn dropdown-toggle btn-xs btn-info" data-toggle="dropdown">
<i class="fa fa-gear"></i> <i class="fa fa-caret-down"></i>
</button>
<ul class="dropdown-menu pull-right">
<li>
Edit
</li>
<li class="divider"></li>
<li>
Delete
</li>
</ul>
</div>
</div>
}
<img src="#item.ArticleImage" class="img-responsive" alt="img" style="width:350px;height:200px">
<ul class="list-inline padding-10">
<li>
<i class="fa fa-calendar"></i>
#item.DateTimeStamp.ToLongDateString()
</li>
<li>
<i class="fa fa-comments"></i>
#item.ArticleComments
</li>
<li>
<i class="fa fa-eye"></i>
#item.ArticleViews
</li>
</ul>
</div>
<div class="col-md-8 padding-left-0">
<h6 class="margin-top-0"> <span style="font-size:large">#item.Title</span><br><small class="font-xs"><i>Published by #item.User_FullName</i></small></h6>
<p>
#Html.Raw(item.Description)
</p>
#*<a class="btn btn-danger" href="#Url.Action("ShowArticleDetails", "ILearn", new { id = item.KnowledgeSharingArticlesId })">Read more</a>*#
<button type="button" onclick="showArticle('#item.KnowledgeSharingArticlesId')" class="btn btn-danger" data-target="#show-details-modal" data-toggle="modal">
Read more
</button>
</div>
</div>
<hr>
}
}
</div>
}
}
}
Modal
This is placed at the top of the page(Under the #model appname.ViewModels.VM):
<!--Loading Panel-->
<div id="loadingPanel" style="display: none;">
<div class="progress progress-striped active">
<div class="progress-bar progress-bar-info" style="width: 100%">...LOADING...</div>
</div>
</div>
<!-- Show details modal-->
<div id="show-details-modal" class="modal fade" style="width:100%">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title"></h4>
<div id="loadingPanelShowDetails" class="col-md-12 text-center" style="display: none;">
<br />
<div class="progress progress-striped active">
<div class="progress-bar progress-bar-info" style="width: 100%">...LOADING...</div>
</div>
</div>
<div id="target-show-details">
</div>
</div>
</div>
</div>
</div>
Jquery Code
function showArticle(id) {
$("#target-show-details").html('');
$('#loadingPanelShowDetails').show();
$.ajax({
type: 'get',
url: '#Url.Action("ShowArticleDetails", "ILearn")',
contentType: 'application/json; charset=utf-8',
dataType: 'html',
data: { "id": id },
success: function (result) {
$("#target-show-details").html(result);
$('#loadingPanelShowDetails').hide();
var saveComment = function (data) {
$(data.pings).each(function (index, id) {
var user = usersArray.filter(function (user) { return user.id == id })[0];
alert(user.fullname);
data.content = data.content.replace('##' + id, '##' + user.fullname);
});
return data;
}
$('#articlecomments-container').comments({
profilePictureURL: 'https://viima-app.s3.amazonaws.com/media/public/defaults/user-icon.png',
currentUserId: 1,
roundProfilePictures: true,
textareaRows: 1,
enableAttachments: true,
enableHashtags: true,
enablePinging: true,
getUsers: function (success, error) {
$.ajax({
type: 'get',
traditional: true,
url: '#Url.Action("GetPinnedUsers", "ILearn")',
success: function (usersArray) {
success(usersArray)
},
error: error
});
},
getComments: function (success, error) {
$.ajax({
type: 'get',
traditional: true,
data: { "id": id },
url: '#Url.Action("GetArticleComments", "ILearn")',
success: function (commentsArray) {
success(saveComment(commentsArray))
},
error: error
});
},
postComment: function (data, success, error) {
$.ajax({
type: 'post',
dataType: "json",
url: '#Url.Action("PostArticleComment", "ILearn")',
data: { "CVM": data, "articleId": id },
success: function (comment) {
success(comment);
},
error: error
});
},
putComment: function (data, success, error) {
$.ajax({
type: 'post',
dataType: "json",
url: '#Url.Action("PutArticleComment", "ILearn")',
data: { "CVM": data, "articleId": id },
success: function (comment) {
success(comment);
},
error: error
});
},
deleteComment: function (data, success, error) {
$.SmartMessageBox({
title: "Deleting Comment?",
content: "Are you sure that you want to delete this comment?",
buttons: '[No][Yes]'
}, function (ButtonPressed) {
if (ButtonPressed === "Yes") {
$.ajax({
type: 'post',
dataType: "json",
url: '#Url.Action("DeleteArticleComment", "ILearn")',
data: { "CVM": data, "articleId": id },
success: function (data) {
if (data.status === "usersuccess") {
$.smallBox({
title: "<strong>Comment Deleted</strong>",
content: "<i class='fa fa-clock-o'></i> <i>Comment was successfully deleted! <strong</strong></i>",
color: "#659265",
iconSmall: "fa fa-check fa-2x fadeInRight animated",
timeout: 4000
});
success();
} else {
success();
}
}
});
}
if (ButtonPressed === "No") {
$.smallBox({
title: "<strong>Comment not deleted</strong>",
content: "<i class='fa fa-clock-o'></i> <i>This comment has not been deleted.</i>",
color: "#C46A69",
iconSmall: "fa fa-times fa-2x fadeInRight animated",
timeout: 4000
});
}
});
e.preventDefault();
},
upvoteComment: function (data, success, error) {
if (data.user_has_upvoted) {
$.ajax({
type: 'post',
dataType: "json",
url: '#Url.Action("UpVoteArticleComment", "ILearn")',
data: { "CVM": data, "articleId": id },
success: function () {
success(data)
},
error: error
});
} else {
$.ajax({
type: 'post',
url: '#Url.Action("DeleteArticleCommentUpvote", "ILearn")',
data: { "commentId": data.id },
success: function () {
success(commentJSON)
},
error: error
});
}
},
uploadAttachments: function (commentArray, success, error) {
var responses = 0;
var successfulUploads = [];
var serverResponded = function () {
responses++;
// Check if all requests have finished
if (responses == commentArray.length) {
// Case: all failed
if (successfulUploads.length == 0) {
error();
// Case: some succeeded
} else {
success(successfulUploads)
}
}
}
$(commentArray).each(function (index, commentJSON) {
// Create form data
var formData = new FormData();
$(Object.keys(commentJSON)).each(function (index, key) {
var value = commentJSON[key];
if (value) formData.append(key, value);
});
formData.append('fkiKnowledgeSharingArticlesId', id);
$.ajax({
url: '#Url.Action("UploadToArticleComments", "ILearn")',
type: 'POST',
data: formData,
cache: false,
contentType: false,
processData: false,
success: function (commentJSON) {
successfulUploads.push(commentJSON);
serverResponded();
},
error: function (data) {
serverResponded();
},
});
});
}
});
},
error: function (xhr, textStatus, errorThrown) {
alert(xhr.responseText);
}
});
}
MVC Partial View
#model Innovation_Cafe.Models.KnowledgeSharingArticles
<div class="col-lg-12">
<div class="margin-top-10">
<div style="text-align:center;border:solid;border-style:solid">
<img src="#Model.ArticleImage" class="img-responsive" alt="img" style="width:100%;">
</div>
<ul class="list-inline padding-10">
<li>
<i class="fa fa-calendar"></i>
#Model.DateTimeStamp.ToLongDateString()
</li>
<li>
<i class="fa fa-comments"></i>
#Model.ArticleComments
</li>
<li>
<i class="fa fa-eye"></i>
#Model.ArticleViews
</li>
</ul>
</div>
</div>
<div class="col-lg-12">
<h6 class="margin-top-0"> #Model.Title<br><small class="font-xs"><i>Published by #Model.User_FullName</i></small></h6>
<br />
<p>
#Html.Raw(Model.Description)
</p>
<p>
#if (Model.FileType == ".mp4")
{
<div style="text-align:center;border-style:solid">
<video controls width="100%">
<source src="#Model.FilePath" type="video/mp4" />
</video>
</div>
}
else
{
if (Model.FilePath !=null)
{
<p>Click here to view file: Click here</p>
}
}
</div>
<div class="col-md-12">
<p> </p>
<hr style="border:solid" />
</div>
<div class="row col-md-12">
<div class="col-md-12" id="articlecomments-container">
</div>
</div>
At the bottom of the partial view is this div where it is populated:
<div class="row col-md-12">
<div class="col-md-12" id="articlecomments-container">
</div>
</div>
EDIT
After spending quite some time running through the jquery-comments.js file, I found that displaying of the pinged users its happening here:
// CUSTOM CODE
// ========================================================================================================================================================================================
// Adjust vertical position
var top = parseInt(this.$el.css('top')) + self.options.scrollContainer.scrollTop();
this.$el.css('top', top);
This seems to be taking the css('top') of View, which causes the problem on the pinging of the users on the partialview.
The issue takes place rather because of your wrong bootstrap layout: you have to include all col into row, whereas in your example you use raw and col-md-12 for the same container.
After I included columns into row elements correctly everything started working the right way. In other words, just write the last section this way:
<div class="row">
<div class="col-md-12" id="articlecomments-container">
</div>
</div>
Please, take a look at an example of nesting in Bootstrap 4.
UPDATE
I've managed to reproduce the mistake thanks to your tip to draw numerous articles on the page. The issue is indeed because of scrolling, though the reason seems to be deeper in jquery.textcomplete.js in a function _fitToBottom (it takes into account the main window scroll but not of the embeded modal container). However, a faster approach I use instead of rectifying that elaborate peice of logic is exactly at the spot which you pointed to (instead of the last 2 rows you showed):
var topPoint = self.options.scrollContainer[0].offsetTop;
var scrolledWindow = self.options.scrollContainer.parents().filter(function () {
return this.scrollTop > 0;
})[0];
var spaceAvailable = $(window).height() - (topPoint - scrolledWindow.scrollTop);
var elHeight = this.$el.height();
this.$el.css('top', spaceAvailable > elHeight ? topPoint: topPoint - elHeight);
The logic is based on looking for the closest parent with scroll and then it measures whether the rest of the space is enough to render the dropdown to figure out its final position. It might slightly miss the pointer, but still works fine in spite of scrolling. I've tried it out in Chrome and Firefox. Hopefully, it will lead you to your own approach.

Show json data in bootstrap modal

Hello Im new to ajax and json and never used modals before. I need to show data which I have already taken into the console. I need to show the data on the console in a modal.
I need to show each specific details of each employee details when I click the view request button. The console is showing the correct details.
javascript
<script>
$(function(){
var BASE_URL = "http://localhost/employeemgt/index.php/";
$('#pedingLeaveRequest').on('show.bs.modal', function(event) {
var button = $(event.relatedTarget);
var current_leave_id = button.data('id');
var modal = $(this);
modal.find('input[name="current_leave_id"]').val(current_leave_id);
});
//approve button
$('#approvebtn').click(function(){
var id = $('input[name="current_leave_id"]').val();
$.post(BASE_URL + 'admin/AdminDashboardController/approveLeave',
{'id': id},
function(result){
console.log(result);
if(result.error){
alert('try again');
}else{
alert('Leave has been approved!');
}
});
});
//disapprove button
$('#declinebtn').click(function(){
var id = $('input[name="current_leave_id"]').val();
$.post(BASE_URL + 'admin/AdminDashboardController/disapproveLeave',
{'id': id},
function(result){
console.log(result);
if(result.error){
alert('try again');
}else{
alert('Leave has been disapproved!');
}
});
});
});
$("#showleave").on('click','button',function(event){
var BASE_URL = "http://localhost/employeemgt/index.php/";
var leave_id = $(this).val();
var response;
$.ajax({
type: 'POST',
dataType: "JSON",
data:{leave_id:leave_id},
url: BASE_URL + 'admin/AdminDashboardController/viewRequest',
success:function(data){
console.log(data);
$('#pendingLeaveRequest #leave_details').html(data);
$('#pendingLeaveRequest').modal('show');
},
error:function(error){
alert(error);
}});
});
</script>
view
<div id="showleave">
<h4 class="mb-4">Pending Requests</h4>
<?php
foreach ($leave as $row) {
if($row->status != "1")
{
echo '
<ul class="list-unstyled">
<li class="media border-bottom border-top py-3">
<img class="mr-3" src="http://via.placeholder.com/64x64" alt="Generic placeholder image">
<div class="media-body">
<h5 class="mt-0 mb-1">'.$row->user_name.'</h5>
<p class="mb-0 mt-0">'.$row->leave_start.' to '.$row->leave_end.'</p>
<p class="mt-0">'.$row->leave_type.'</p>
<button type="button" class="detailButton" href="<?php echo $id; ?>" data-id="'.$row->id.'" data-name="'.$row->user_name.'" data-target="#pendingLeaveRequest" data-toggle="modal" value="'.$row->id.'">View Request</button>
</div>
</li>
</ul>
';
}
}
?>
</div>
modal
<!-- Modal -->
<div class="modal fade" id="pendingLeaveRequest" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Leave Request</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" id="leave_details" >
<p>
</p>
</div>
<div class="modal-footer">
<input type="hidden" name="current_leave_id" id="current_leave_id" value="" />
<button type="button" id="declinebtn" class="btn btn-secondary" data-dismiss="modal">Decline</button>
<button type="button" id="approvebtn" class="btn btn-primary">Approve</button>
</div>
</div>
</div>
</div>
controller
public function viewRequest()
{
$leave_id = $this->input->post('leave_id');
$data = $this->Admin_Model->viewRequest($leave_id);
echo json_encode($data);
}
Use below code in your ViewRequest function, remove my previous codes.
$("#showleave").on('click','button',function(event){
var BASE_URL = "http://localhost/employeemgt/index.php/";
var leave_id = $(this).val();
var response;
$.ajax({
type: 'POST',
dataType: "JSON",
data:{leave_id:leave_id},
url: BASE_URL + 'admin/AdminDashboardController/viewRequest',
success:function(data){
console.log(data);
$('#pendingLeaveRequest #leave_details').html(data);
$('#pendingLeaveRequest').modal('show');
},
error:function(error){
alert(error);
}});
});

Javascript methods stop working after writing another method in the same script tag

I have written a code on codeigniter framework for approve and disapprove leave of employees. The approval and disapproval worked fine before. But after I write another methods in the same script tag for showing the leave details of the employees the approval and disapproval stopped working.
What can I change in order to make the two buttons work. The two buttons are also inside the modal.
javascript
<script>
$(function(){
var BASE_URL = "http://localhost/employeemgt/index.php/";
$('#pedingLeaveRequest').on('show.bs.modal', function(event) {
var button = $(event.relatedTarget);
var current_leave_id = button.data('id');
var modal = $(this);
modal.find('input[name="current_leave_id"]').val(current_leave_id);
});
//approve button
$('#approvebtn').click(function(){
var id = $('input[name="current_leave_id"]').val();
$.post(BASE_URL + 'admin/AdminDashboardController/approveLeave',
{'id': id},
function(result){
console.log(result);
if(result.error){
alert('try again');
}else{
alert('Leave has been approved!');
}
});
});
//disapprove button
$('#declinebtn').click(function(){
var id = $('input[name="current_leave_id"]').val();
$.post(BASE_URL + 'admin/AdminDashboardController/disapproveLeave',
{'id': id},
function(result){
console.log(result);
if(result.error){
alert('try again');
}else{
alert('Leave has been disapproved!');
}
});
});
});
//show leave details on modal
$("#showleave").on('click','button',function(event){
var BASE_URL = "http://localhost/employeemgt/index.php/";
var leave_id = $(this).val();
$.ajax({
type: 'POST',
dataType: "JSON",
data:{leave_id:leave_id},
url: BASE_URL + 'admin/AdminDashboardController/viewRequest',
success:function(data){
console.log(data);
$('#leave_details').html(data);
$('#pendingLeaveRequest').modal('show');
},
error:function(error){
alert(error);
}});
});
</script>
view:
<div id="showleave">
<h4 class="mb-4">Pending Requests</h4>
<?php
foreach ($leave as $row) {
if($row->status != "1")
{
echo '
<ul class="list-unstyled">
<li class="media border-bottom border-top py-3">
<img class="mr-3" src="http://via.placeholder.com/64x64" alt="Generic placeholder image">
<div class="media-body">
<h5 class="mt-0 mb-1">'.$row->user_name.'</h5>
<p class="mb-0 mt-0">'.$row->leave_start.' to '.$row->leave_end.'</p>
<p class="mt-0">'.$row->leave_type.'</p>
<button type="button" class="detailButton" href="<?php echo $id; ?>" data-id="'.$row->id.'" data-name="'.$row->user_name.'" data-toggle="modal" value="'.$row->id.'">View Request</button>
</div>
</li>
</ul>
';
}
}
?>
</div>
modal
<!-- Modal -->
<div class="modal fade" id="pendingLeaveRequest" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Leave Request</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" id="leave_details" >
<p> </p>
</div>
<div class="modal-footer">
<input type="hidden" name="current_leave_id" id="current_leave_id" value="" />
<button type="button" id="declinebtn" class="btn btn-secondary" data-dismiss="modal">Decline</button>
<button type="button" id="approvebtn" class="btn btn-primary">Approve</button>
</div>
</div>
</div>
</div>
As you are replacing the $('#pendingLeaveRequest #leave_details').html(data); with new data so the button don't work.. Try to replace it with new id....
//show leave details on modal
//$("#showleave").on('click',function(){
$('.detailButton').on('click', function(){
var BASE_URL = "http://localhost/employeemgt/index.php/";
var leave_id = $(this).val();
$.ajax({
type: 'POST',
dataType: "JSON",
data:{leave_id:leave_id},
url: BASE_URL + 'admin/AdminDashboardController/viewRequest',
success:function(data){
console.log(data);
$('#leave_details p').html(data);
$('#pendingLeaveRequest').modal('show');
},
error:function(error){
alert(error);
}});
});
let me know if it is working..

Calling a MVC controller using jQuery and ajax

Hello I am trying to call a method with parameters in my controller using ajax and jquery
Controller:
[HttpPost("{Id}")]
public ActionResult PostComment(int Id, ShowViewModel model)
{
}
View:
I have a button called AddComment, when clicked it should open a modal popup which asks for confirmation to save
<form id="addCommentForm" asp-action="postcomment" enctype="multipart/form-data">
<button id="addCommentButton" class="btn btn-primary">
<i class="fa fa-search"></i> Add comment
</button>`
<div class="modal fade" id="saveConfirmationDialog" tabindex="-1" role="dialog" aria-labelledby="saveConfirmationDialogTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="saveConfirmationDialogTitle">Post selective exchange comment</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Do you want to post a comment?
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-success">
<i class="fa fa-envelope-open"></i> Post selective exchange comment
</button>
<button type="button" class="btn btn-danger" data-dismiss="modal">
<i class="fa fa-ban"></i> Close
</button>
</div>
</div>
</div>
</div>
</form>
Javascript:
ControllerName.View.Properties.controllerViewUrl = $("#controllerViewUrl").val();
$(document).ready(function () {
ControllerName.View.Validation.initialize();
ControllerName.View.Initialize.addCommentButton();
});
ControllerName.View.Initialize = {}
ControllerName.View.Initialize.addCommentButton = function () {
$('#addCommentButton').click(function (event) {
event.preventDefault();
if ($('#addCommentForm').valid()) {
$("#saveConfirmationDialog").modal('show');
}
});
}
ControllerName.View.Validation = {}
ControllerName.View.Validation.initialize = function () {
$("#addCommentForm").validate();
}
ControllerName.View.Ajax = {}
ControllerName.View.Ajax.postComment = function (successCallback) {
var url = ControllerName.View.Properties.controllerViewUrl + '/PostComment'+<<parameter>>;
}
My Controller method is not getting called, what am I doing wrong?
I also need to pass a Id as parameter
Please help, Thanks in advance
A simple example
HTML CODE
<button id="saveButton" type="button" data-toggle="modal" data-target="#saveConfirmationDialog" class="btn btn-labeled btn-danger" style="display:none;">Save Data</button>
<div id="saveConfirmationDialog" class="modal fade" role="dialog" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 id="modal-title" class="modal-title">Post selective exchange comment</h4>
</div>
<div class="modal-body">
Do you want to post a comment?
</div>
<div class="modal-footer">
<div id="formDiv">
<button id="sender" type="submit" class="btn btn-success"><i class="fa fa-envelope-open"></i> Post selective exchange comment</button>
<button type="button" class="btn btn-danger" data-dismiss="modal"><i class="fa fa-ban"></i> Close</button>
</div>
<div id="loadingPanel" style="display:none;">Loading...</div>
</div>
</div>
</div>
</div>
JS CODE
<script type="text/javascript">
$('#sender').click(function () {
PostDataToController();
});
function PostDataToController(action) {
$('#formDiv').hide();
$('#loadingPanel').show();
// create form data
var formData = new FormData();
formData.append("YourParameter", $('#YourValue').val());
// Write here your parameters what you need
// do post
$.ajax({
type: "POST",
url: "/localhost:8080/InsertComment",
enctype: "multipart/form-data",
cache: false,
contentType: false,
processData: false,
data: formData,
success: function (d) {
$('#formDiv').show();
$('#loadingPanel').hide();
if (d.result == "ok") {
/*Your success operations*/
}
else {
//alert(d.msg);
/*Your custom error operations*/
}
},
error: function (xhr, textStatus, errorThrown) {
/*Your error operations*/
//alert(xhr);
$('#formDiv').show();
$('#loadingPanel').hide();
}
});
}
</script>
MVC CODE
[HttpPost]
public ActionResult InsertComment(int Id, ShowViewModel model)
{
if (ModelState.IsValid)
{
// insert
// Yor save method is here
if (!isSuccess()) // your process not succeeded
{
// error
return Json(new { result = "no", msg = /*your error message*/ });
}
//succeeded
return Json(new { result = "ok" });
}
else
{
// error
string error = ModelState.Values.FirstOrDefault(f => f.Errors.Count > 0).Errors.FirstOrDefault().ErrorMessage;
return Json(new { result = "no", msg = error });
}
}

Categories

Resources