I am following this guide (https://softdevpractice.com/blog/asp-net-core-mvc-ajax-modals/) for my Modals, and got everything working except for the last part which closes the Modal when it saves without errors. Essentially what the article shows is to add an IsValid input tag that's hidden and stores the ModelState which would be used to determine whether or not it is a successful save and should close the modal.
// find IsValid input field and check it's value
// if it's valid then hide modal window
var isValid = newBody.find('[name="IsValid"]').val() == 'True';
if (isValid) {
placeholderElement.find('.modal').modal('hide');
}
Would love any input on this. My code is as follows:
View
<div id="AddStudyModal"></div>
// unrelated code here
<button type="button" class="btn btn-secondary" data-toggle="ajax-modal" data-bs-target="#add-study" data-url="#Url.Action("AddStudy", "App", new {id = Model.GUID})">Add</button>
Partial View
#model AddStudyViewModel
<div class="modal fade" id="add-study" tabindex="-1" role="dialog" aria-labelledby="addStudyLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addStudyLabel">Add Study</h5>
<button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form asp-controller="App" asp-action="AddStudy" method="post">
<input name="IsValid" type="hidden" value="#ViewData.ModelState.IsValid.ToString()"/>
#Html.HiddenFor(m => m.ParticipantGuid)
<div asp-validation-summary="ModelOnly"></div>
<div class="mb-3 form-group">
#* <label asp-for="Studies" class="form-label"></label> *#
<select asp-for="SelectedStudyGuid" asp-items="#ViewBag.Studies" class="form-control" autocomplete="off">
#* <select asp-for="SelectedStudyGuid" asp-items="#Model.Studies" class="form-control" autocomplete="off"> *#
<option value="">Select Study</option>
</select>
<span asp-validation-for="SelectedStudyGuid" class="text-danger"></span>
</div>
<div class="mb-3 form-group">
<label asp-for="StartDate" class="form-label"></label>
<input asp-for="StartDate" class="form-control" autocomplete="off"/>
<span asp-validation-for="StartDate" class="text-danger"></span>
</div>
<div class="mb-3 form-group">
<label asp-for="EndDate" class="form-label"></label>
<input asp-for="EndDate" class="form-control" autocomplete="off"/>
<span asp-validation-for="EndDate" class="text-danger"></span>
</div>
<div class="text-center">
</div>
<div class="text-center">#ViewBag.Message</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" data-save="modal">Save</button>
</div>
</div>
</div>
</div>
Site.Js
$(function (){
var AddStudyElement = $('#AddStudyModal');
$('button[data-toggle="ajax-modal"]').click(function(event){
var url = $(this).data('url');
$.get(url).done(function(data){
AddStudyElement.html(data);
AddStudyElement.find('.modal').modal('show');
})
})
AddStudyElement.on('click', '[data-save="modal"]', function(event){
event.preventDefault();
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
var sendData = form.serialize();
// $.post(actionUrl, sendData).done(function(data){
// AddStudyElement.find('.modal').modal('hide');
// })
$.post(actionUrl, sendData).done(function (data) {
var newBody = $('.modal-body', data);
AddStudyElement.find('.modal-body').replaceWith(newBody);
// find IsValid input field and check it's value
// if it's valid then hide modal window
var isValid = newBody.find('[name="IsValid"]').val() == 'True';
if (isValid) {
AddStudyElement.find('.modal').modal('hide');
}
});
});
});
Edit: After more examination it seems like my issue may be related to my RedirectToAction. I have posted my controller action below
[HttpPost]
public IActionResult Study(StudyViewModel model)
{
if (ModelState.IsValid)
{
var response= _repo.AddEditStudy(model.StudyGuid,model.SelectedStudyCatalogGuid, model.ParticipantGuid, model.StartDate, model.EndDate);
if (response.Success)
{
TempData["Message"] = response.Message;
return RedirectToAction("EditParticipant", new {id = model.ParticipantGuid});
}
}
model.Studies = GetStudyCatalog();
return PartialView("_StudyModal", model);
}
Related
I am working on laravel project, I have a modal form and user can add new fields which I added dynamically using jquery and it works well, but the problem is when I send the form values to the controller the values of the newly dynamic fields is not send or like they lost when the modal is closed after submit, any help?
this is the modal code:
<div class="modal fade" id="{{$task->id}}" tabindex="-1" role="">
<div class="modal-dialog modal-login modal-lg" role="document">
<div class="modal-content">
<div class="card card-signup card-plain">
<div class="modal-header">
<h5 class="modal-title card-title" id="exampleModalLabel">Edit Task</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form >
<div class="form-row">
<div class="form-group col-md-12">
<input type="text" class="form-control" name="issue"
value="{{$task->issue}}">
</div>
</div>
<div class="form-row pt-2">
<div class="form-group col-md-6">
<select name="tag" id="tag" class="form-control" >
<option value="{{$task->tag}}" selected>{{$task->tag}}</option>
#if($task->tag=='CM')
<option value="PM">PM</option>
#else
<option value="CM">CM</option>
#endif
</select>
</div>
</div>
<div class="form-row pt-2">
<div class="form-group col-md-12">
<textarea class="form-control" name="root_cause"
placeholder="Root Cause"></textarea>
</div>
</div>
<div class="form-row pt-2">
<div class="col-md-8 form-group" id="container{{$task->id}}">
<select class="form-control" name="add_used_part[]" >
<option disabled selected>used spare parts</option>
#foreach($task->machine->part as $part)
<option value="{{$part->id}}"> {{$part->part_name}}
</option>
#endforeach
</select>
</div>
<div class="form-group col-md-4" id="container2{{$task->id}}">
<input type="text" class="form-control " id="quantity"
name="quantity[]" placeholder="Quantity">
</div>
Add another spare part
</div>
<div class="modal-footer justify-content-center">
<button type="button" class="btn btn-primary"
onclick="submitajax('{{$task->id}}') ; return
false;">Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
this jquery function:
<script type="text/javascript">
function addField(a,b){
var parts = JSON.parse(a);
// Container <div> where dynamic content will be placed
var container1 = document.getElementById("container"+b);
var container2 = document.getElementById("container2"+b);
//Create and append select list
var selectList = document.createElement("select");
selectList.name="add_used_part[]";
container1.append(selectList);
//Create and append the options
for (var i = 0; i < parts.length; i++) {
var option = document.createElement("option");
option.value = parts[i].id;
option.text = parts[i].part_name;
selectList.append(option);
}
var input = document.createElement("input");
input.type = "text";
input.name = "q";
container2.append(input);
}
function submitajax(id){
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
var tag = $("#tag").val();
var add_used_part= $("[name='add_used_part[]']").val();
var quantity= $("[name='quantity[]']").val();
/* this alert only one value of the add_used_part and quantity arrays
alert (id+tag+' '+add_used_part+' '+quantity);
$.ajax({
type:'POST',
url:"{{ route('task.update',['id' => $task->id ] ) }}",
data:{tag:tag, add_used_part:add_used_part, quantity:quantity},
success:function(data){
alert(data.success);
}
});
}
I think the problem is in this fragment:
var add_used_part= $("[name='add_used_part[]']").val();
var quantity= $("[name='quantity[]']").val();
You can't read many values this way, maybe you can try something like this:
var add_used_part= [];
$.each( $("[name='add_used_part[]']"), function(){
add_used_part.push( $(this).val() )
})
var quantity= [];
$.each( $("[name='quantity[]']"), function(){
quantity.push( $(this).val() )
})
And then send these arrays via AJAX request.
P.S: Sorry, I saw the question date just now :)
I'm validating fields inside modal popup,for single field it is working but if more than one field are appended at a time then validation does not takes place on those fields. Here we can see we add new field by adding add field button but those newly field did'nt get validated.
$(function() {
$("#newModalForm").validate();
$('.form-control').each(function() {
required($(this))
});
$(document).on('click', '#add_field', function(e) {
$('#dynamic_div').html("<div class=form-group><label class=control-label col-md-3 for=email>Dynamic field 1:</label> <inputname=sfs type=text class=form-control></div> <div class=form-group><label class=control-label col-md-3 for=email>Dynamic field 2:</label><input name=ssf type=text class=form-control></div>");
required($(this))
});
function required(el) {
el.rules("add", {
required: true,
messages: {
required: "This field is required",
}
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.14.0/jquery.validate.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#addMyModal">Open Modal</button>
<div class="modal fade" id="addMyModal" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Add Stuff</h4>
</div>
<div class="modal-body">
<form role="form" id="newModalForm">
<div class="form-group">
<label class="control-label col-md-3" for="email">A p Name:</label>
<div class="col-md-9">
<input type="text" class="form-control" id="pName" name="pName" placeholder="Enter a p name"/>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="email">Action:</label>
<div class="col-md-9">
<input type="text" class="form-control" id="action" name="action" placeholder="Enter and action">
</div>
</div>
<div class="col-md-9" id="dynamic_div">
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-success" id="btnSaveIt">Save</button>
<button type="button" id="add_field" class="btn btn-default">Add Field</button>
<button type="button" class="btn btn-default" id="btnCloseIt" data-dismiss="modal">Close</button>
</div>
</form>
</div>
</div>
</div>
</div>
You need call .each() on the dynamically added elements as well.
Dynamically added elements are not in DOM onload so ideally you need to do wrap .each() in a function when you add more fields to your modal just call that function again to check for empty inputs
To handle submit and store data we can .submit on your modal form. Get all the data via .serialize method and send all your form data to the backend file via ajax request.
Run Snippet below to see it working.
$(function() {
//Validate Data
var validate = $("#newModalForm").validate()
checkInput()
//Add dynamic inputs
$(document).on('click', '#add_field', function(e) {
$('#dynamic_div').html("<div class=form-group><label class=control-label col-md-3 for=email>Dynamic field 1:</label> <input name=sfs type=text class=form-control></div> <div class=form-group><label class=control-label col-md-3 for=email>Dynamic field 2:</label><input name=ssf type=text class=form-control></div>");
//Required Dynamic Input
checkInput()
});
//Validate all inputs
function checkInput() {
$('.form-control').each(function() {
required($(this))
});
}
//Required field message
function required(el) {
el.rules("add", {
required: true,
messages: {
required: "This field is required",
}
});
}
//Submit form modal
$('#newModalForm').on('submit', function(e) {
//Prevent default submit behaviour
e.preventDefault()
//Store all the form modal form data
var data = $(this).serialize()
//Check all fieild have data
if (validate.errorList.length == 0) {
alert('All fields have value - Form will submit now')
//Request to backend
$.ajax({
url: 'your_url',
type: 'POST',
data: data,
success: function(response) {
//do something on success
},
error: function(xhr) {
//Handle errors
}
});
}
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.14.0/jquery.validate.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#addMyModal">Open Modal</button>
<div class="modal fade" id="addMyModal" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Add Stuff</h4>
</div>
<div class="modal-body">
<form role="form" method="post" id="newModalForm">
<div class="form-group">
<label class="control-label col-md-3" for="email">A p Name:</label>
<div class="col-md-9">
<input type="text" class="form-control" id="pName" name="pName" placeholder="Enter a p name" />
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="email">Action:</label>
<div class="col-md-9">
<input type="text" class="form-control" id="action" name="action" placeholder="Enter and action">
</div>
</div>
<div class="col-md-9" id="dynamic_div">
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-success" id="btnSaveIt">Save</button>
<button type="button" id="add_field" class="btn btn-default">Add Field</button>
<button type="button" class="btn btn-default" id="btnCloseIt" data-dismiss="modal">Close</button>
</div>
</form>
</div>
</div>
</div>
</div>
I've got a modal window that is submitting a form to a database via ajax and if an error occurs it will return a json response. This has been working well on modal windows with only one input field, but I have another modal window with 2 fields and the json response correctly returns error messages, for instance:
As you can see, both fields with the error are in the response. Like I said, my script works fine and will show the error for a form with only one text input, but I have two in this form (ignore the first select element, it is pre-filled via ajax). Here's my script that handles the ajax success and error responses:
$(document).ready(function () //function to process modal form via ajax
{
$('.modal-submit').on('submit', function(e){
e.preventDefault(); //prevent default form submit action
var data = $(this).serialize();
var type = $(this).find('input[name="type"]').val(); //get value of hidden input
var url = $(this).attr('action'); //get action from form
var modal = $(this).closest('.modal');
var modalInput = $(this).find('.form-row input'); //get input from form
var modalId = $(this).closest('.modal').attr('id');
$.ajax({
url:url,
method:'POST',
data:data,
success:function(response){
refreshData(newId = response.id, modalId); // set newId to the id of the newly inserted item, get modalId
modal.modal('hide'); //hide modal
$(modalInput).val(''); //clear input value
},
error:function(response){
$.each(response.responseJSON.error, function (i, error) {
console.log(data);
console.log(response.responseJSON.error);
$(modalInput).addClass('input-error');
$('#' + modalId + ' .backend-error').html(error[0]); //return error from backend
});
}
});
});
});
Here's the html for the modal window with multiple inputs:
<!-- Add New Model Modal -->
<div class="modal fade" id="modelModal" tabindex="-1" role="dialog" aria-labelledby="modelModalLabel" 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="modelModalLabel">Add new asset model</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form method="post" class="modal-submit" autocomplete="off" action="{{ action('AddAssetController#addDescriptor', ['type' => 'model']) }}">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="hidden" name="type" value="model">
<div class="form-row">
<div class="col-md-12 mb-3">
<label for="inputManufacturerModel">Manufacturer *</label>
<div class="input-group">
<select name="inputManufacturerModel" id="inputManufacturerModel" class="form-control" required="required" onclick="refreshData()">
<option value="0">Select manufacturer...</option>
</select>
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-12 mb-3">
<label for="inputModelNew">New model name *</label>
<div class="input-group">
<input type="text" name="inputModelNew" id="inputModelNew" class="form-control" placeholder="Add manufacturer model name" required="required">
</div>
<div class="backend-error"></div>
</div>
</div>
<div class="form-row">
<div class="col-md-12 mb-3">
<label for="inputModelNoNew">New model # *</label>
<div class="input-group">
<input type="text" name="inputModelNoNew" id="inputModelNoNew" class="form-control" placeholder="Add manufacturer model #" required="required">
</div>
<div class="backend-error"></div>
</div>
</div>
<div class="float-right">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save changes</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- / Add New Model Modal -->
Result of error response:
Do I need to loop over the errors? How do I get the relevant error to show under the correct input field?
In ajax error don't use this
$(modalInput).addClass('input-error') because this will add the class to all modal's input and this will set the error to all modal's input. $('#' + modalId + ' .backend-error').html(error[0]);
Use input Id to set error like in your case $('#inputModelNew').parent('.input-group').siblings('.backend-error').addClass('input-error').html(error[0])
here is the html file
it contains a model popup with fields name and email id. I need to edit and update them
<tr ng-repeat="item in collection">
<a ng-click=readOne(item.id) data-toggle="modal" data-target="#myModal">Edit</a>
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="modal-product-title">Edit</h4>
</div>
<div class="modal-body">
<div><b style='color: red'>{{modalstatustext}}</b></div>
<form id="form-dinminder">
<div class="form-group">
<label for="name" class="control-label">Name</label>
<input ng-model="name" type="text" class="form-control" id="form-name" placeholder="Name">
</div>
<div class="form-group">
<label for="email" class="control-label">Email ID</label>
<input ng-model="email" type="text" class="form-control" id="form-email" placeholder="Email ID">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button id="btn-update-product" type="button" class="btn btn-warning" ng-click="updateProduct()">Save changes</button>
</div>
</div>
</div>
</div>
</td>
</tr>
controller.js
/***********edit************/
$scope.readOne=function(id){
console.log("selected agency id",id)
adminservice.selectedAgency(id).then(function(response){
$scope.aid = response.data[0].id;
$scope.name=response.data[0].name;
$scope.email=response.data[0].webaddress;
//update modal
$('#myModal').modal('show');
},function(error){
$scope.modalstatustext = "Unable to Update data!";
});
}
$scope.updateProduct=function(id){
var Name = $scope.name;
var Email = $scope.email;
service.updateAgency(Name,Email).then(function(response){
//alert(response.data);
$('#myModal').modal('hide');
showAll();//after updating all items are shown
},function(error){
console.log("error in updating ");
});
}
service.js
var updateAgency=function(Name,Email){
return $http({
method: "POST",
url: CONFIG.apiurl + 'edit',
params:{
name:Name,
webaddress:Email
}
});
i have no idea what i have done wrong.
Backend seems to work perfectly.
thanks
Your UpdateProduct function expects a parameter of id,
<button id="btn-update-product" type="button" class="btn btn-warning" ng-click="updateProduct(passidhere)">Save changes</button>
Remove the id parameter from your updateProduct function as this is not used.
I'm new in javascript. can you help me?
I've a js modal popup which loaded whenever user visits my website. in that modal popup I've a login form and I'm trying to login a user through javascript. I've a user.txt file where I've record of users.it doesn't show any error message or page. popup comes again and again
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 style="color:red;"> Login</h4></div>
<div class="modal-body">
<form role="form" >
<div class="form-group">
<label for="usrname"> Username</label>
<input type="text" name="username" class="form-control" id="usrname" placeholder="Enter username" required/>
</div>
<div class="form-group">
<label for="psw"> Email</label>
<input type="email" name="Email" class="form-control" id="email" placeholder="Enter Email" required/>
</div>
<span id="loginSpan" style="color:Red"></span>
<button type="submit" onclick="LoginFunction()" class="btn btn-
default btn-success "> Login</button>
</form>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-default btn-default pull-left" data-dismiss="modal"> Cancel</button>
<p>Not a member? <a href="#myModal2" data-toggle="modal">Sign Up</</p>
</div>
</div>
</div>
</div>
and my javascript as follow for login
<script>
function LoginFunction(){
var email= $("#email").val();
var usern= $("#usrname").text();
var text = ReadFile();
var lines = text.split(";");
var text = readFile();
lines.pop();
if(email==text[2] && usern==text[1]){
window.location("index.html");
}
else{
var span=document.getElementById("loginSpan");
span.text="username or email does not match";
}
};
function ReadFile(){
var fso = new ActiveXObject("Scripting.FileSystemObject");
var fh = fso.OpenTextFile("user.txt", 1, false, 0);
var lines = "";
while (!fh.AtEndOfStream) {
lines += fh.ReadLine();
}
fh.Close();
return lines;
}
</script>