The event in jquery popup is triggered more than once - javascript

I am working on a survey application using Asp.net MVc. My events in jquery popup are triggered more than once. The more a popup is opened, the more it triggers in the event in the popup. What is the reason of this. Every time browsers are opened, the temporary javascript file that starts with the VM is removed. When the popup is closed, these opened virtual javascript files are not destroyed. What is the reason of this?
These events include adding rows to the table, updating and deleting rows.The AddOrEdit.cshtml file contains both screen components and javascript codes.
Images;
AddOrEdit.cshtml(Jquery Popup)
#using MerinosSurvey.Models
#model Questions
#{
Layout = null;
}
#using (Html.BeginForm("AddOrEdit", "Question", FormMethod.Post, new { onsubmit = "return SubmitForm(this)", onreset = "return ResetForm(this)", id = "questionForm" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group row">
#Html.Label("QuestionId", "Soru No", new { #class = "col-form-label col-md-3" })
<div class="col-md-9">
#Html.TextBoxFor(model => model.QuestionId, new { #readonly = "readonly", #class = "form-control", })
</div>
</div>
<div class="form-group row">
#Html.Label("QuestionName", "Soru Adı", new { #class = "col-form-label col-md-3" })
<div class="col-md-9">
#Html.EditorFor(model => model.QuestionName, new { htmlAttributes = new { #class = "form-control"
} })
#Html.ValidationMessageFor(model => model.QuestionName)
</div>
</div>
<div class="form-group row">
<div class="col-md-9 offset-md-3">
<div class="custom-control custom-checkbox">
#Html.CheckBoxFor(m => m.IsOtherOptionRequired, new { #class = "custom-control-input ", id = "IsOtherOptionRequired", })
<label class="custom-control-label" for="IsOtherOptionRequired">Diğer Seçeneği Eklensin mi?
</label>
</div>
</div>
</div>
<br>
<hr class="style14">
<br>
#Html.ValidationMessageFor(model => model.Options)
<div class="table-wrapper form-group table-responsive-md">
<div class="table-title">
<div class="form-group row">
<div class="col-md-9">Options</div>
<div class="col-md-3">
<button type="button" class="btn btn-success add-new" style="margin-bottom: 10px"><i class="fa fa-plus"></i>Add Option</button>
</div>
</div>
</div>
<table class="table optionTable">
<thead class="thead-light">
<tr>
<th style="display:none;" width="20%" scope="col">Seçenek Id</th>
<th scope="col">Option Name</th>
<th width="25%" scope="col">Update/Delete</th>
</tr>
</thead>
<tbody>
#foreach (Options options in Model.Options)
{
<tr>
<td style="display:none;">#options.OptionId</td>
<td>#options.OptionName</td>
<td>
<a class="add btn btn-primary btn-sm" title="Add" data-toggle="tooltip">
<i class="fa fa-check">Approve</i>
</a>
<a class="edit btn btn-secondary btn-sm" title="Edit" data-toggle="tooltip">
<i class="fa fa-pencil">Update</i>
</a>
<a class="delete btn-danger btn-sm" title="Delete" data-toggle="tooltip">
<i class="fa fa-trash">Delete</i>
</a>
</td>
</tr>
}
</tbody>
</table>
</div>
<div class="form-group row d-flex justify-content-end">
<button type="submit" class="btn btn-primary" style="margin-bottom: 10px; color: black"><i class="fa fa-save"></i>Kaydet</button> </div>
}
Jquery add, edit, delete click events
<script>
$(document).ready(function () {
$('[data-toggle="tooltip"]').tooltip();
//var actions = $("table.optionTable td:last-child").html();
var actions =
' <a class="add btn btn-primary btn-sm" title="Add" data-toggle="tooltip"><i class="fa fa-check">Onayla</i></a>' +
'<a class="edit btn btn-secondary btn-sm" title="Edit" data-toggle="tooltip"><i class="fa fa-pencil">Güncelle</i></a>' +
'<a class="delete btn-danger btn-sm" title="Delete" data-toggle="tooltip"><i class="fa fa-trash">Sil</i></a>';
// Append table with add row form on add new button click
$(".add-new").click(function () { //RUNS MULTIPLE TIMES ON CHROME
debugger;
$(this).attr("disabled", "disabled");
$(".btnSubmit").attr("disabled", "disabled");
var index = $("table.optionTable tbody tr:last-child").index();
var row = '<tr>' +
'<td style="display:none;">0</td>' +
'<td><input type="text" class="form-control" name="optionName" id="optionName"></td>' +
'<td>' +
actions +
'</td>' +
'</tr>';
$("table.optionTable").append(row);
$("table.optionTable tbody tr").eq(index + 1).find(".add, .edit").toggle();
$('[data-toggle="tooltip"]').tooltip();
});
// Add row on add button click
$(".add").click(function () { //RUNS MULTIPLE TIMES ON CHROME
debugger;
var empty = false;
var input = $(this).parents("tr").find('input[type="text"]');
input.each(function () {
if (!$(this).val().trim()) {
$(this).addClass("error");
empty = true;
} else {
$(this).removeClass("error");
}
});
$(this).parents("tr").find(".error").first().focus();
if (!empty) {
input.each(function () {
$(this).parent("td").html($(this).val().trim());
});
$(this).parents("tr").find(".add, .edit").toggle();
$(".add-new").removeAttr("disabled");
$(".btnSubmit").removeAttr("disabled");
}
});
// Edit row on edit button click
$(".edit").click(function () { //RUNS MULTIPLE TIMES ON CHROME
debugger;
/*td: nth - child(2)*/
//$(this).parents("tr").find("td:nth-child(2)").each(function () {
$(this).parents("tr").find("td:not(:first-child, :last-child)").each(function () {
$(this).html('<input type="text" class="form-control" value="' + $(this).text() + '">');
});
$(this).parents("tr").find(".add, .edit").toggle();
$(".add-new").attr("disabled", "disabled");
$(".btnSubmit").attr("disabled", "disabled");
});
// Delete row on delete button click
$(".delete").click(function () {//RUNS MULTIPLE TIMES ON CHROME
debugger;
$(this).parents("tr").remove();
$(".add-new").removeAttr("disabled");
var rowCount = $('table.optionTable tbody tr').length;
if (rowCount > 0) {
$(".btnSubmit").removeAttr("disabled");
} else {
$(".btnSubmit").attr("disabled", "disabled");
}
});
});

It seems you are binding event multiple time by using class selector. It means After adding new DOM in the document, bind a click event on newly added action buttons, but it is binding click event on existing action buttons also.
So simple tick to solve your problem is you have to unbind existing click event and bind new once.
$(".add-new").unbind('click').bind('click', function(){
//your code here
});
$(".add").unbind('click').bind('click', function(){
//your code here
});
$(".edit").unbind('click').bind('click', function(){
//your code here
});
$(".delete").unbind('click').bind('click', function(){
//your code here
});

You can use jQuery on/off methods to handle this.
$(".add-new").off('click').on('click', function(){
});

When you open popup for the second time I believe running $(".add-new").length will return 2 for you. Try to resolve that first which will automatically resolve your events problem.
Do changes such that $(".add-new").length is always 1

Related

How can I get this javascript function to work all of the time? (Uncaught TypeError: Cannot read properties of null)

I'm trying to create two numerical inputs, each of which has their own custom '+' and '-' buttons. However, with my current code, it appears that the button functions only work some of the time. On the other occasions I get a Uncaught TypeError: Cannot read properties of null (reading 'value') at HTMLButtonElement.<anonymous> error.
This is the HTML:
<div class="col">
<div class="row">
<div class="input-group mx-auto w-50">
<div class="input-group-prepend">
<button class="btn btn-dark btn-sm minus" data-id="one"
type="button"><i class="fa fa-minus"></i></button>
</div>
<input type="number" id="one"
class="form-control form-control-sm text-center" value="0">
<div class="input-group-prepend">
<button class="btn btn-dark btn-sm plus" data-id="one" type="button"><i
class="fa fa-plus"></i></button>
</div>
</div>
</div>
<div class="row">
<div class="input-group mx-auto w-50">
<div class="input-group-prepend">
<button class="btn btn-dark btn-sm minus" data-id="two"
type="button"><i class="fa fa-minus"></i></button>
</div>
<input type="number" id="two"
class="form-control form-control-sm text-center" value="0">
<div class="input-group-prepend">
<button class="btn btn-dark btn-sm plus" data-id="two" type="button"><i
class="fa fa-plus"></i></button>
</div>
</div>
</div>
</div>
And this is the Javascript:
<script>
document.addEventListener("DOMContentLoaded", () => {
document.querySelectorAll('.minus').forEach(item => {
item.addEventListener('click', event => {
var input_id = event.target.getAttribute('data-id')
console.log('Minus button clicked for input ' + input_id)
var quantityInput = document.getElementById(input_id);
var currentQuantity = parseInt(quantityInput.value);
quantityInput.value = currentQuantity - 1
})
})
document.querySelectorAll('.plus').forEach(item => {
item.addEventListener('click', event => {
var input_id = event.target.getAttribute('data-id')
console.log('Plus button clicked for input ' + input_id)
var quantityInput = document.getElementById(input_id);
var currentQuantity = parseInt(quantityInput.value);
quantityInput.value = currentQuantity + 1
})
})
})
Here is a sample of the output after clicking a few of the buttons:
The event.target may be the span inside the button, and therefore the code may not find the data-id attribute. Instead perhaps get the id without using event.target. Either use item or event.currentTarget.
the click event happend on the <i class="fa fa-minus"></i>
you may use Event.currentTarget instead of event.target
document.addEventListener("DOMContentLoaded", () =>
{
document.querySelectorAll('.minus').forEach(item =>
{
item.onclick = event =>
{
let
input_id = event.currentTarget.dataset.id
, quantityInput = document.getElementById(input_id)
, currentQuantity = parseInt(quantityInput.value)
;
console.log('Minus button clicked for input ' + input_id)
quantityInput.value = currentQuantity - 1
}
})
document.querySelectorAll('.plus').forEach(item =>
{
item.onclick = event =>
{
let
input_id = event.currentTarget.dataset.id
, quantityInput = document.getElementById(input_id)
, currentQuantity = parseInt(quantityInput.value)
;
console.log('Plus button clicked for input ' + input_id)
quantityInput.value = currentQuantity + 1
}
})
})
you can also simply do:
document.addEventListener("DOMContentLoaded", () =>
{
document
.querySelectorAll('button.minus, button.plus')
.forEach( btn => // this is the button
{
btn.onclick = () => // no event argument needed
{
let
input_Qte = document.getElementById( btn.dataset.id )
, adding = btn.classList.contains('plus') ? +1 : -1
;
input_Qte.value = +input_Qte.value + adding // use +input_Qte.value for integer conversion
}
})
})
Replace quantityInput.value with quantityInput?.value

jquery Validate Casuing Initail invalid elements to become valid on second 'save' button click

So, I am trying to use jQuery Validate to check for duplicate values in a form, and it's working for the most part. However, I am getting the following weird behavior:
The user will enter a couple duplicate values, and click save
jQuery Validate will show 'Duplicate Name' in the UI for each of the duplicate values
The user does not fix the duplicate values, but rather, adds another duplicate value
The user clicks save again, and the previous two invalid elements are marked valid, and the Duplicate Name message disappears, but the third value is correctly marked as invalid.
If the user clicks save again, then all three error messages are shown correctly.
If the user clicks on save without correcting any, the client-side validation is not followed and the server-side errors are shown for duplicate values.
Basically, I'm wondering what is wrong with my jQuery validation logic? Is it that I'm not forcing a revalidation every time the save button is clicked?
Here is my jQuery Validation code:
$.validator.addMethod("checkForDuplicateClaimName", function (value, element) {
console.log('calling checkDuplicateClaimName')
var customClaimForm = $("form.form-horizontal");
var claimRepeated = 0;
if (value != '') {
var matchingClaims = 0;
// Loop through the whole form to find duplicate claim names
customClaimForm.children().each(function (count, item) {
// Have to iterate through the custom claim div to find the names
if ($(item).attr("id") === "custom-claims-div") {
var customClaimDiv = $("#custom-claims-div");
customClaimDiv.children().each(function (count, claim) {
var customClaimNameToCompare = $(claim).find('label').text();
if (value == customClaimNameToCompare) {
matchingClaims++;
}
});
}
// Not the custom claim div, just the labels from the default scopes
else {
var nameToCompare = $(item).find('label').text();
if ((value == nameToCompare)) {
matchingClaims++;
}
}
});
}
return matchingClaims === 1 || matchingClaims === 0;
}, "Duplicate Name");
$.validator.addClassRules("duplicateClaimName", {
checkForDuplicateClaimName: true
});
var validate = $("form.form-horizontal").validate({
ignore: "", // This checks hidden input values, which is what we want for the claim name validation
errorElement: 'div',
errorClass: 'custom-claim-validation-error',
errorPlacement: function (error, element) {
error.appendTo($(element).parent().find("#claim-name-lbl"))
},
submitHandler: function (form) {
console.log('calling submit handler');
form.submit();
}
});
$('form.form-horizontal').submit(function () {
console.log('calling submit form');
console.log(validate);
});
Here is the code for when a new claim is added to the custom-claims-div. It is the code that adds the class duplicateClaimName for jquery validation.
function oidc_addCustomProfileClaim() {
// Grab the custom claim name and value
var customAttName = $("#dialog-add-custom-scope-claim #customAttName").val();
var customAttValue = $("#dialog-add-custom-scope-claim #customAttValue").val();
// Get the last index of the custom claim div
var lastId: number = -1;
var div = $("#custom-claims-div");
if ($("#custom-claims-div").children().length) {
lastId = parseInt($("#custom-claims-div").children().last().attr("data-id"), 10);
}
lastId++;
// Create the new form-group
var newDiv = $("<div data-id=\"" + lastId + "\" id=\"claim-info-div\" class=\"form-group row\">");
newDiv.append("<label data-id=\"" + lastId + "\" id=\"claim-name-lbl\" name=\"CustomClaims[" + lastId + "].ClaimLabel\" class=\"col-sm-2 control-label no-padding-right\" style=\"padding-right: 10px! important;\" value=\"" + customAttName + "\">" + customAttName + "</label>");
//Need to make a hidden input so that the model will be correctly filled when passed to the controller
newDiv.append("<input data-id=\"" + lastId + "\" id=\"claim-value\" name=\"CustomClaims[" + lastId + "].ClaimValue\" type=\"text\" class=\"col-md-5\" value=\"" + customAttValue + "\" />")
newDiv.append("<input id=\"hidden-claim-value\" name=\"CustomClaims[" + lastId + "].ClaimLabel\" class=\"duplicateClaimName\" type=\"hidden\" value=\"" + customAttName + "\" />")
// Create the label for disabling/enabling the claim
newDiv.append("<input data-id=\"" + lastId + "\" id=\"disable-claim-chkbx\" name=\"CustomClaims[" + lastId + "].IsDisabled\" style=\"margin-left: 75px;\" type=\"checkbox\" value=\"false\"/>");
// Create the Button
var button = $("<button class=\"btn btn-xs btn-white btn-danger\" data-action=\"delete\" style=\"margin-left: 79px; width=80px;\" type=\"button\">");
var deleteText = $("<i class=\"ace-icon fa fa-trash-o fa-lg\">");
// Build the form group
button.append(deleteText);
button.append(" Delete");
newDiv.append(button);
div.append(newDiv);
}
This is the modal JS to add a new claim to the form:
$("#dialog-add-custom-scope-claim").dialog({
autoOpen: false,
resizable: false,
modal: true,
width: 420,
title: "<div class=\"widget-header\">Add a new profile custom scope</div>",
title_html: true,
buttons: [
{
text: "Add",
"class": "btn btn-primary btn-xs no-border",
click: function () {
oidc_addCustomProfileClaim();
$('#new-claim-name-form').find('#customAttName').val('');
$('#new-claim-value-form').find('#customAttValue').val('');
$(this).dialog("close");
}
},
{
text: "Cancel",
"class": "btn btn-xs no-border",
click: function () {
$('#new-claim-name-form').find('#customAttName').val('');
$('#new-claim-value-form').find('#customAttValue').val('');
$(this).dialog("close");
}
}
]
});
The elements in question have the correct duplicateClaimName class in the HTML:
<input id="hidden-claim-value" name="CustomClaims[#i].ClaimLabel" type="hidden" class="duplicateClaimName" value="#Model.CustomClaims[i].ClaimLabel" />
Thanks in advance for any input!
Edit:
Here is the relevant HTML for my form submit button, if it helps:
#using (Html.BeginFormWithCss("form-horizontal"))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "Please, fix the following errors.", new { #class = "alert alert-block alert-danger no-style-list" })
<h3 class="header smaller lighter green">Scope profile</h3>
<div class="form-group">
<label class="col-sm-2 control-label no-padding-right">Name</label>
<div class="col-sm-10">
<input id="Name" name="Name" type="text" data-auto="attributes" class="col-xs-12 col-md-4" value="#Model.Name" />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label no-padding-right">FamilyName</label>
<div class="col-sm-10">
<input id="FamilyName" name="FamilyName" type="text" data-auto="attributes" class="col-xs-12 col-md-4" value="#Model.FamilyName" />
</div>
</div>
<div id="custom-claims-div" class="form-group">
#if (#Model.CustomClaims.Count() > 0)
{
for (int i = 0; i < #Model.CustomClaims.Count(); i++)
{
<div data-id="#i" id="claim-info-div" class="form-group row">
<label data-id="#i" id="claim-name-lbl" name="CustomClaims[#i].ClaimLabel" class="col-sm-2 control-label no-padding-right" style="padding-right: 10px !important;" value="#Model.CustomClaims[i].ClaimLabel">#Model.CustomClaims[i].ClaimLabel</label>
<input data-id="#i" id="claim-value" name="CustomClaims[#i].ClaimValue" type="text" data-auto="attributes" class="col-md-5" value="#Model.CustomClaims[i].ClaimValue" />
<input id="hidden-claim-value" name="CustomClaims[#i].ClaimLabel" type="hidden" value="#Model.CustomClaims[i].ClaimLabel" />
#if (Model.CustomClaims[i].IsDisabled)
{
<input data-id="#i" id="disable-claim-chkbx" name="CustomClaims[#i].IsDisabled" style="margin-left: 75px;" type="checkbox" checked="checked" value="true" />
}
else
{
<input data-id="#i" id="disable-claim-chkbx" name="CustomClaims[#i].IsDisabled" style="margin-left: 75px;" type="checkbox" value="false" />
}
<button class="btn btn-xs btn-white btn-danger" data-action="delete" style="margin-left: 75px;" type="button">
<i class="ace-icon fa fa-trash-o fa-lg"></i>
Delete
</button>
</div>
}
}
</div>
<div id="dialog-add-custom-scope-claim" class=modal>
<div>
<div id="new-claim-name-form" class="form-group">
<label class="control-label">Claim Name</label>
<input id="customAttName" style="margin-bottom: 10px" type="text" value="" class="col-xs-12" placeholder="Claim Name" />
</div>
<div id="new-claim-value-form" class="form-group">
<label class="control-label">Claim Value</label>
<input id="customAttValue" type="text" value="" class="col-xs-12" placeholder="Claim Value (attribute name from FID)" />
</div>
</div>
</div>
<div class="clearfix form-actions">
<div class="col-md-offset-1 col-md-9">
<button class="btn btn-info" type="submit">
<i class="ace-icon fa fa-check fa-lg"></i>
Save
</button>
<a class="btn" href="#Url.Action("Index")">
<i class="ace-icon fa fa-times fa-lg"></i>
Cancel
</a>
</div>
</div>

Limit the number of times a button can be pressed - C# ASP.NET MVC5 JavaScript

I have a page that allows you to create Income Types, but if you click the Create button, in succession then it creates multiple entries, Is there a way to have it limit this to you press it once and that is it?
I have looked at the code it uses an ajax method to get the information then post the form to the database. Some of my code below:
Index
#section scripts {
<script language="javascript" type="text/javascript">
#* DOM ready? *#
$(function () {
#* Pagination Async Partial Handling *#
$(document).on("click", "#indexPager a", function () {
if ($(this).parent().hasClass('disabled') || $(this).parent().hasClass('active'))
return false;
$.ajax({
url: $(this).attr("href"),
type: 'GET',
cache: false,
success: function (result) {
$('#tableContainer').html(result);
addBootstrapTooltips("#tableContainer");
}
});
return false;
});
$(document).on("change", "#pageSizeSelector", function () {
var selectedValue = $(this).val();
$.ajax({
url: selectedValue,
type: 'GET',
cache: false,
success: function(result) {
$('#tableContainer').html(result);
addBootstrapTooltips("#tableContainer");
}
});
});
#* Sorting Async Partial Handling *#
$(document).on("click", "#tableHeader a", function () {
$.ajax({
url: $(this).attr("href"),
type: 'GET',
cache: false,
success: function (result) {
$('#tableContainer').html(result);
addBootstrapTooltips("#tableContainer");
}
});
return false;
});
#* Apply ACTION colours for hover *#
addTableStylingScripts();
});
</script>
}
#section additionalStyles {
#Styles.Render("~/plugins/datatables/media/css/cssDatatables")
}
#section modal {
}
<article class="row">
<h1 class="pageTitle artistHeader fw200 mb20 mt10">#ViewBag.Title</h1>
<div class="col-md-12">
<div class="panel panel-visible" id="tableContainer">
#Html.Partial("_IncomeTypeManagementList", Model)
</div>
</div>
</article>
IncomeTypeManagementList
#* Header *#
<div class="panel-heading createContentTitle">
<div class="panel-title createLink">
<a href="#Url.Action("Create", "IncomeTypeManagement", new
{
page = Model.PagingInfo.Page,
take = Model.PagingInfo.Take,
sortBy = Model.PagingInfo.SortPropertyName,
sortAsc = Model.PagingInfo.SortAscending
})" data-container="body" data-toggle="tooltip" title="Add Income Type" id="createIncomeTypeLink">
<span class="fa fa-file"></span> Add Income Type
</a>
</div>
</div>
#* Body *#
<div class="panel-body pn">
<table class="table table-striped table-hover dataTable incomeTypesTable admin-form theme-primary" cellspacing="0" width="100%" role="grid">
<thead id="tableHeader">
<tr>
<th class="hidden-xs sorting #Html.SortTitleItem("IncomeTypeGroupId", Model.PagingInfo.SortPropertyName, Model.PagingInfo.SortAscending)">
<a href="#Url.Action("Index", "IncomeTypeManagement", new
{
page = 1,
take = Model.PagingInfo.Take,
sortBy = "IncomeTypeGroupId",
sortAsc = Model.PagingInfo.SortPropertyName != "IncomeTypeGroupId" || !Model.PagingInfo.SortAscending
})" data-container="body" data-toggle="tooltip" title="Sort by group">Group</a>
</th>
<th class="sorting #Html.SortTitleItem("Name", Model.PagingInfo.SortPropertyName, Model.PagingInfo.SortAscending)">
<a href="#Url.Action("Index", "IncomeTypeManagement", new
{
page = 1,
take = Model.PagingInfo.Take,
sortBy = "Name",
sortAsc = Model.PagingInfo.SortPropertyName != "Name" || !Model.PagingInfo.SortAscending
})" data-container="body" data-toggle="tooltip" title="Sort by name">Name</a>
</th>
<th class="hidden-xs sorting hidden-xs #Html.SortTitleItem("CreatedDate", Model.PagingInfo.SortPropertyName, Model.PagingInfo.SortAscending)">
<a href="#Url.Action("Index", "IncomeTypeManagement", new
{
page = 1,
take = Model.PagingInfo.Take,
sortBy = "CreatedDate",
sortAsc = Model.PagingInfo.SortPropertyName != "CreatedDate" || !Model.PagingInfo.SortAscending
})" data-container="body" data-toggle="tooltip" title="Sort by date">Created</a>
</th>
<th class="bg-white">
<div class="text-center">Action</div>
</th>
</tr>
</thead>
<tbody>
#foreach (var it in Model.IncomeTypes)
{
var actionId = "action_" + tableRowIndex;
var editIncomeTypeId = "editIncomeType_" + tableRowIndex;
<tr data-id="#it.ID"
data-isdeleted="#it.IsDeleted"
data-rowversion="#it.RowVersion"
data-createddate="#it.CreatedDate"
data-name="#it.Name"
data-incometypegroupid="#it.IncomeTypeGroupId"
data-incometypegroupname="#it.IncomeGroupName">
<td class="hidden-xs">
#it.IncomeGroupName
</td>
<td>
#it.Name.Truncate(50)
</td>
<td class="hidden-xs">
#it.CreatedDate.ToShortDateString()
</td>
<td class="updateTableRow text-center">
<div class="dropdownContainer btn-group text-right">
<button type="button" class="btn btn-primary br2 btn-xs fs12 dropdown-toggle" data-toggle="dropdown" aria-expanded="false" id="#actionId">
Action
<span class="caret ml5"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right" role="menu">
<li>
<a href="#Url.Action("Update", "IncomeTypeManagement", new
{
id = it.ID,
page = Model.PagingInfo.Page,
take = Model.PagingInfo.Take,
sortBy = Model.PagingInfo.SortPropertyName,
sortAsc = Model.PagingInfo.SortAscending
})" data-container="body" data-toggle="tooltip" id="#editIncomeTypeId" title="Edit" data-rowhover="editTableRow">
Edit
</a>
</li>
</ul>
</div>
</td>
</tr>
tableRowIndex++;
}
</tbody>
</table>
#Html.Partial("_Pagination", Model.PagingInfo)
</div>
Create
#section scripts {
#Scripts.Render("~/bundles/jqueryajaxval")
#Scripts.Render("~/bundles/jqueryval")
<script language="javascript" type="text/javascript">
$(document).ready(function () {
#* Cancel *#
$(document).on("click", "#CancelForm", function (e) {
var uri = '#Html.Raw(Url.Action("Index", "IncomeTypeManagement", new
{
page = Model.PagingInfo.Page,
take = Model.PagingInfo.Take,
sortBy = Model.PagingInfo.SortPropertyName,
sortAsc = Model.PagingInfo.SortAscending
}))';
window.location = uri;
e.preventDefault();
});
});
</script>
}
#section additionalStyles {
}
#section modal {
}
<article class="row">
<h1 class="pageTitle incomeTypeHeader fw200 mb20 mt10">#ViewBag.Title</h1>
<div class="col-md-1"></div>
<div id="incomeTypeResults" class="col-md-10 formContainer">
<div class="panel">
<div class="panel-heading">
<span class="panel-title">
<i class="glyphicon glyphicon-pencil"></i> Details Of New Income Type
</span>
</div>
#using (Html.BeginForm("Create",
"IncomeTypeManagement", FormMethod.Post,
new { id = "createIncomeType", role = "form", #class = "theme-primary form-horizontal" }))
{
#Html.AntiForgeryToken()
#* Pagination / Sorting *#
#Html.HiddenFor(m => m.PagingInfo.Page)
#Html.HiddenFor(m => m.PagingInfo.Take)
#Html.HiddenFor(m => m.PagingInfo.SortPropertyName)
#Html.HiddenFor(m => m.PagingInfo.SortAscending)
<fieldset>
<legend style="display: none">Create Income Type Form</legend>
#Html.HiddenFor(m => m.IsDeleted)
<div class="panel-body p25 fill bt0">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.IncomeTypeGroupId, new { #class = "control-label col-lg-2" })
<div class="col-lg-8">
#{
// get drop down values for DropDownFor()
var selectableItems = incomeTypeGroups.Select((v, idx) => new SelectListItem
{
Text = v.Value,
Value = v.Key,
Selected = idx == 0
});
}
#Html.DropDownListFor(m => m.IncomeTypeGroupId, selectableItems, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.IncomeTypeGroupId, string.Empty, new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Name, new { #class = "control-label col-lg-2" })
<div class="col-lg-8">
#Html.TextBoxFor(m => m.Name, new { #class = "form-control", id = "Name", placeholder = "Name..." })
#Html.ValidationMessageFor(m => m.Name, string.Empty, new { #class = "text-danger" })
</div>
</div>
</div>
<div class="panel-footer">
<div class="text-center">
<input type="button" class="btn btn-primary" id="CancelForm" value="Cancel" />
<input type="submit" class="btn btn-primary" id="SubmitForm" value="Create" />
</div>
</div>
</fieldset>
}
</div>
</div>
</article>
Update
section scripts {
#Scripts.Render("~/bundles/jqueryajaxval")
#Scripts.Render("~/bundles/jqueryval")
<script language="javascript" type="text/javascript">
$(document).ready(function () {
#* Cancel *#
$(document).on("click", "#CancelForm", function (e) {
var uri = '#Html.Raw(Url.Action("Index", "IncomeTypeManagement", new
{
page = Model.PagingInfo.Page,
take = Model.PagingInfo.Take,
sortBy = Model.PagingInfo.SortPropertyName,
sortAsc = Model.PagingInfo.SortAscending
}))';
window.location = uri;
e.preventDefault();
});
});
</script>
}
#section additionalStyles {
}
#section modal {
}
<article class="row">
<h1 class="pageTitle incomeTypeHeader fw200 mb20 mt10">#ViewBag.Title</h1>
<div class="col-md-1"></div>
<div id="incomeTypeResults" class="col-md-10 formContainer">
<div class="panel">
<div class="panel-heading">
<span class="panel-title">
<i class="glyphicon glyphicon-pencil"></i> Details Of '#Model.Name'
</span>
</div>
#using (Html.BeginForm("Update",
"IncomeTypeManagement", FormMethod.Post,
new { id = "updateIncomeType", role = "form", #class = "theme-primary form-horizontal" }))
{
#Html.AntiForgeryToken()
#* Pagination / Sorting *#
#Html.HiddenFor(m => m.PagingInfo.Page)
#Html.HiddenFor(m => m.PagingInfo.Take)
#Html.HiddenFor(m => m.PagingInfo.SortPropertyName)
#Html.HiddenFor(m => m.PagingInfo.SortAscending)
<fieldset>
<legend style="display: none">Edit Income Type Form</legend>
#Html.HiddenFor(m => m.ID)
#Html.HiddenFor(m => m.RowVersion)
#Html.HiddenFor(m => m.IsDeleted)
<div class="panel-body p25 fill bt0">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.IncomeTypeGroupId, new { #class = "control-label col-lg-2" })
<div class="col-lg-8">
#{
// get drop down values for DropDownFor()
var selectableItems = incomeTypeGroups.Select((v, idx) => new SelectListItem
{
Text = v.Value,
Value = v.Key,
Selected = Model.IncomeTypeGroupId.ToString() == v.Key
});
}
#Html.DropDownListFor(m => m.IncomeTypeGroupId, selectableItems, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.IncomeTypeGroupId, string.Empty, new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Name, new { #class = "control-label col-lg-2" })
<div class="col-lg-8">
#Html.TextBoxFor(m => m.Name, new { #class = "form-control", id = "Name", placeholder = "Name..." })
#Html.ValidationMessageFor(m => m.Name, string.Empty, new { #class = "text-danger" })
</div>
</div>
</div>
<div class="panel-footer">
<div class="text-center">
<input type="button" class="btn btn-primary" onclick="this.disabled = true" id="CancelForm" value="Cancel" />
<input type="submit" class="btn btn-primary" id="SubmitForm" value="Update" />
</div>
</div>
</fieldset>
}
</div>
</div>
</article>
So I have tried adding <input type="submit" class="btn btn-primary" id="SubmitForm" value="Update" onclick="this.disabled = true" />
On the Create page When you click on Add Income Tye you are directed to the Create page, but when I have tied testing it the button is disabled, but then it does not submit anything and just remains on the Create page
To answer your question you kind of have to tackle the problem from 2 angles:
once click happens on your button you can either disable it or show an overlay so that no other elements on the page can be interacted with
you also have to think of what happens if some malicious user replays that request multiple times (by bypassing or altering the UI - which is dead easy to do) - on the server side you can use a processing queue of requests and every time you want to add a new request for processing, you can check to see if a duplicate exists
Unfortunately there isn't an easy answer for this. The 2nd part of the answer you have to think about it and assess if you're exposed to this issue. If your application is public and anyone can access it, don't assume that users will do everything on your system just via the UI.
Hope this helps.
This is what I come up with:
<script language="javascript" type="text/javascript">
$('.form-disable').on('submit', function () {
var self = $(this),
button = self.find('input[type="submit"], button'),
submitValue = button.data('submit-value');
button.attr('disabled', 'disabled').val((submitValue) ? submitValue : 'Please Wait...');
});
</script>
I added a class to the form so that when you click on a button that handles the submit, it disables the button and then waits with a message. But it only allows the button to be clicked once.

Using ajax to check radiobutton by Id in ASP.Net MVC

I saw a code that checks the radio button by value, but how do I do this by id? My current scenario is that I'm populating a table by appending html codes using ajax. I'm looping the prices of a certain item while building the html table. After that, I need to check the radio button of a price where default flag is equal to 'Y'.
Here's my if statement that checks the radiobutton by value only, this is not working yet as my radiobutton values are null, only the id and name has value:
if (item.defaultflag == 'Y')
$('#divItemPrice').find(':radio[name=rbDefaultPrice][value="iPrice_' + item.channelid + '"]').prop('checked', true);
else
$('#divItemPrice').find(':radio[name=rbDefaultPrice][value="iPrice_' + item.channelid + '"]').prop('checked', false);
Complete code:
$.ajax({
url: '/Item/RetrievePrice',
type: 'POST',
dataType: 'json',
data: JSON.stringify(json),
contentType: 'application/json; charset=utf-8',
cache: false,
async: true,
success: function (data) {
var trHTML = "";
debugger;
trHTML = '<tbody id="dbBody2">';
$.each(data, function (i, item) {
trHTML += '<tr><td class="hidden">' + item.itemid + '</td>' +
'<td style="width:20px"><label><input type="radio" name="rbDefaultPrice" id = "iPrice_' + item.itemid + '" /></label></td>' +
'<td>' + item.itemprice + '</td>' +
'<td>' + ToJavaScriptDate(item.startdate) + '</td>' +
'<td>' + ToJavaScriptDate(item.enddate) + '</td>' +
'</tr>';
//How do I check the radiobutton by id?
if (item.defaultflag == 'Y')
$('#divItemPrice').find(':radio[name=rbDefaultPrice][value="iPrice_' + item.itemid + '"]').prop('checked', true);
else
$('#divItemPrice').find(':radio[name=rbDefaultPrice][value="iPrice_' + item.itemid + '"]').prop('checked', false);
});
trHTML += '</tbody>';
$("#tblItemPrice tbody").remove();
$('#tblItemPrice').append(trHTML);
},
error: function (xhr, ajaxOptions, thrownError) {
alert("Error! " + xhr.status);
}
});
View (modal part)
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<div id="divItemPrice" class="" style="border: 0px solid green; ">
<table id="tblItemPrice" onclick="gettabledata('tblItemPrice', '0,2,3,4', 'itemPriceId,itemPrice,strtDt,endDt')" class="table table-hover table-bordered table-striped bootgrid-table" aria-busy="false" padding-left:10px;">
<thead>
<tr class="inner-table-head">
<th class="hidden">
#Html.DisplayNameFor(model => model.itemPriceId)
</th>
<th>
Price
</th>
<th>
Start Date
</th>
<th>
End Date
</th>
</tr>
</thead>
<tbody id="bodyToAppend">
</tbody>
</table>
</div>
<div class="form-group">
<div class="row form-row">
<span class="form-item">
#Html.HiddenFor(m => m.itemPriceId)
#Html.LabelFor(m => m.itemPrice, new { #class = "lbl-width" })
#Html.TextBoxFor(m => m.itemPrice, new { #class = "form-control input-sm" })
</span>
</div>
<div class="row form-row">
<span class="form-item ">
#Html.LabelFor(m => m.strtDt, new { #class = "lbl-width" })
#Html.TextBoxFor(m => m.strtDt, new { #class = "form-control input-sm", #Value = "" })
</span>
</div>
<div class="row form-row">
<span class="form-item ">
#Html.LabelFor(m => m.endDt, new { #class = "lbl-width" })
#Html.TextBoxFor(m => m.endDt, new { #class = "form-control input-sm", #Value = "" })
</span>
</div>
<div class="row form-row maintenance-btn">
<div class="btn-group">
<input type="submit" id="btnSavePrice" value="Save" class="btn btn-theme btn-sm" formmethod="post" />
<input type="submit" id="btnUpdatePrice" value="Update" class="btn btn-theme btn-sm" formmethod="post" style="display:none" />
#*<input type="submit" id="btnCancelPrice" value="Cancel" class="btn btn-theme btn-sm" />*#
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button id="closeModal" type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
The code in your if/else block cannot work because its attempting to .find() and element in the DOM which does not even exist yet (you have not added it). And even if you did add the <tr> to the DOM in each iteration it would result in poor performance (searching the whole table in each iteration).
A simple way to solve this (and much easier to debug the html your generating) is to create a hidden template that is cloned and added in each iteration. I also assume that you want to add the value of itemprice as the value attribute of the radio button so that you can get the value of the selected radio button using var price = $('input[name="rbDefaultPrice"]').val();
<table id="template" style="display:none;">
<tr>
<td>
<label>
<input type="radio" name="rbDefaultPrice" class="radio" />
<span class="price"></span>
</label>
</td>
<td class="startdate"></td>
<td class="enddate"></td>
</tr>
</table>
Then in the .each() loop, clone the template, update its values and append it to the DOM
var tbody = $('#tblItemPrice tbody');
....
success: function (data) {
tbody.empty() // remove existing rows
$.each(data, function (i, item) {
// clone the template row
var row = $('#template').clone().find('tr');
// update properties
var radio = row.find('.radio');
radio.val(item.itemprice);
if (item.defaultflag == 'Y') {
radio.prop('checked', true);
}
row.find('.price').text(item.itemprice);
row.find('.startdate').text(....
// add the row to the DOM
tbody.append(row);
});
}
Side note: Its not clear what your ToJavaScriptDate() function is doing, but I suggest you just pass the correctly formatted value to client so you can just use row.find('.startdate').text(item.startdate); etc

Asp.net MVC 5 : CRUD in modal dialog using javascript

I 'm newebie in Asp.net MVC 5
So , I have a simple project in which i'm usiong asp.net . I have an object named :
Object { Id, Code, Name} .
I want to list the Objects in grid , edit , add and remove .
I am able to show the list and add new object .
Those operations are in modal dialog .
I have some problems now :
How to send the Object to the action Controller then show it or edit itinto a modal dialog using javascript when i choose it ?
The second picture is when i click add new Object , it shows me the modal dialog , and all works fine with the Add , biut not with the others actions.
My Code
ObjectController :
public ActionResult AddObject()
{
if (Request.IsAjaxRequest())
return PartialView(dd);
return View(dd);
}
[HttpPost]
public ActionResult AddObject(ModelObject model)
{
/* Working Code */
}
AddObject partial View :
#using (Ajax.BeginForm("AddObject", "Object",
new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "msgAdd",
OnSuccess = "addSuccess",
OnFailure = "addFailure"
},
new { #class = "form-horizontal" }))
{
#Html.ValidationSummary(true);
<div class="row" style="padding: 5px 0 5px 0">
<div class="col-lg-12">
<div class="col-lg-12 border no-margin" style="padding:10px 0px 10px 0 !important">
<div class="form-group" style="align-content:center">
<label class="col-sm-4 control-label">Code </label>
<div class="col-lg-6">
#Html.TextBoxFor(m => m.Code, new { #class = "form-control", placeholder = "Code" })
#Html.ValidationMessageFor(m => m.Code)
</div>
<label class="col-sm-4 control-label">Libellé </label>
<div class="col-lg-6">
#Html.TextBoxFor(m => m.Name, new { #class = "form-control", placeholder = "Libellé " })
#Html.ValidationMessageFor(m => m.Name)
</div>
</div>
</div>
</div>
</div>
<div class="hr-line-solid no-margin"></div>
<div class="row" style="padding: 5px 0 5px 0">
<div class="col-sm-1 col-sm-offset-4">
<button type="reset" class="btn btn-outline btn-primary"><i class="icon-refresh icon-white"></i> Réinitialiser</button>
</div>
<div class="col-sm-3 col-sm-offset-4">
<button type="reset" class="btn btn-default right" data-dismiss="modal">Annuler</button>
<input type="submit" value="Enregistrer" class="btn btn-success right" />
</div>
</div>
<div id="msgAdd" style="display:none">
</div>
}
</div>
ListObjects View :
<tbody>
#foreach (var m in Model.objects)
{
<tr class="gradeX">
<td id="idObject" style="display:none;"><span class="hideextra">#m.Id</span></td>
<td><span class="hideextra">#m.Code</span></td>
<td><span class="hideextra">#m.Name</span></td>
<td class="infont">
<center>
<a id="btnEdit"><i class="fa fa-pencil-square-o text-"></i></a>
<i class="fa fa-trash-o text-danger"></i>
<i class="fa fa-search text-navy"></i>
</center>
</td>
</tr>
}
</tbody>
Javascript :
1- For adding :
$(document).ready(function () {
//jQuery.noConflict();
$("#btn").click(function () {
var url = "AddObject"; // the url to the controller
$.get(url, function (data) {
$("#saisieJDiag").draggable({
handle: ".modal-header"
});
$("#saisieJDiag").resizable();
$("#saisieJDiag").html(data);
$("#saisieJDiag").modal("show");
$('#saisieJDiag').on('shown.bs.modal', function () {
$('.chosen-select', this).chosen();
});
$('.i-checks').iCheck({
checkboxClass: 'icheckbox_square-green',
radioClass: 'iradio_square-green',
});
});
});
});
</script>
Now I want the same approch but to edit and show the obecjt on the modal , how i can do that !

Categories