Pulling value from a serialized array - Form Validation - javascript

I have a form:
<form role="form" id="emailForm" action="#" th:action="#{/emailSubmission}" th:object="${university}" method="post">
<div class="form-group">
<input type="hidden" th:field="*{id}" ></input>
<p>
<label for="emailID"><span class="glyphicon glyphicon-envelope"></span> Email</label>
<input type="email" class="form-control" name="emailID" id="emailID" field="email" th:field="*{email}" placeholder="Enter email"></input></p>
<p>
<label for="uniID"><span class="glyphicon glyphicon-book"></span> University Name</label>
<input type="text" class="form-control" name="uniID" id="uniID" field="uniName" th:field="*{uniName}" placeholder="Enter University Name"></input></p>
<p>
<label for="adminID"><span class="glyphicon glyphicon-user"></span> Administrator name</label>
<input type="text" class="form-control" name="adminID" id="adminID" field="adminName" th:field="*{adminName}" placeholder="Enter Aministrator Name"></input></p>
</div>
<button type="button" id="submitButton" class="btn btn-default btn-success btn-block" data-dismiss="modal" ><span class="glyphicon glyphicon-check"></span> Register</button>
</form>
And some jQuery:
//submit form validation
$("#submitButton").click(function(event) {
var form_data = $("#emailForm").serializeArray();
var error_free = true;
for (var input in form_data) {
var element = $('#' + form_data[input]['name']);
var valid = element.hasClass("is-valid");
if (!valid) {
error_free = false;
}
}
if (!error_free) {
event.preventDefault();
} else {
sendEmail();
};
});
My problem is with the line:
var element=$('#' + form_data[input]['name']);
It'm trying to return $('#emailID') etc but can't seem to get this to work. Any help would be appreciated.

After talking with you in the comment, here is the output of your form_data var :
Array(4)
0 : {name: "id", value: "0"}
1 : {name: "email", value: "test#uni.ac.uk"}
2 : {name: "uniName", value: "aUni"}
3 : {name: "adminName", value: "anAdmin"}
According to your HTML, it refered to your "field" attr and not your "name", so to select them, change this :
var element = $('#' + form_data[input]['name']);
to this :
var element = $("input[field='" + form_data[input]['name'] + "']");
or this (as suggested in the comment by #Taplar) :
var element = $('input').filter('[field="'+ form_data[input]['name'] +'"]');
Is it ok for you?

Related

how to pass the input type in jQuery to ajax

I have a basic bootstrap form, and I want to pass the input type through to php via ajax. I can get the input name & value with serializeArray().
How would I extend the output from serializeArray to also include the input 'type'?
Some more info... Here's my current form...
<form id="second_example_form" class="form-horizontal core_form_submission" action="#" method="post" data-callback="<?php echo __DIR__ . '/form-second-example.callback.php'; ?>">
<div class="form-group">
<label class="col-sm-2 control-label" for="email">Email</label>
<div class="col-sm-5">
<input id="email" class="form-control" required type="email" placeholder="Email" name="email">
</div>
<div class="col-sm-5 messages"></div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Submit</button>
</div>
</div>
And here's the ajax calling js...
$('#form').on('submit', function(e) {
e.preventDefault();
var data = form.serializeArray();
$.post('ajax/forms.ajax.php', {
data: data
}, function(r) {
var json = JSON.parse(r);
}
});
var data = form.serializeArray(); works great to pass the name and value... but doesn't include input type.
Can anyone help?
Serialize does not provide that, you would have to construct name value of all the types and pass that to your server.
$('form').on('submit', function(e) {
e.preventDefault();
var formData = $(this).serializeArray();
$('input, select', this).each(function() {
formData.push({
name: $(this).attr('name') + '_type',
value: $(this).prop('tagName').toLowerCase()
});
});
console.log(formData);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="second_example_form" class="form-horizontal core_form_submission" action="#" method="post" data-callback="<?php echo __DIR__ . '/form-second-example.callback.php'; ?>">
<div class="form-group">
<label class="col-sm-2 control-label" for="email">Email</label>
<div class="col-sm-5">
<input id="email" class="form-control" required type="email" placeholder="Email" name="email">
</div>
<div class="col-sm-5 messages"></div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Submit</button>
</div>
</div>
</form>
You can not do this normal serializeArray function I did quick fix and sharing code with two alternative.
$(document).ready(function(){
//Make sure name and id will be same id=email_email name = email_email
var fields = $( "#second_example_form" ).serializeArray();
fields = fields.map(function(val){
val.type = $( "#"+val.name ).attr("type");
return val;
});
console.log(fields);
//Change only name and add type with name seprated by _ like this name = name_type
var fields = $( "#second_example_form" ).serializeArray();
fields = fields.map(function(val){
val.type = val.name.split("_")[1]
return val;
});
console.log(fields);
});
body, select {
font-size: 14px;
}
form {
margin: 5px;
}
p {
color: red;
margin: 5px;
}
b {
color: blue;
}
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<form id="second_example_form" class="form-horizontal core_form_submission" action="#" method="post" data-callback="<?php echo __DIR__ . '/form-second-example.callback.php'; ?>">
<div class="form-group">
<label class="col-sm-2 control-label" for="email">Email</label>
<div class="col-sm-5">
<input id="email_email" class="form-control" required type="email" placeholder="Email" name="email_email">
</div>
<div class="col-sm-5 messages"></div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Submit</button>
</div>
</div>
</form>
I ended up doing a mixture of the other answers, to create a new array from scratch.
// Collect all of the fields in the form, their values and types
function gather_form_fields(form)
{
var output = {};
form.find(':input').each(function(){
var type = $(this).attr('type'),
name = $(this).attr('name'),
val = $(this).val();
// If it's a select or other element without a 'type', return the element
if (type == null) {
type = $(this).prop('tagName').toLowerCase();
}
// remove the submit button
if (type == 'submit') {
return true;
}
output[name] = {
type: type,
name: name,
value: val
};
});
return output;
}
This then produces an object with the type, name and value e.g.
data = {
first_name: {
name: "first_name",
type: "text",
value: "joe"
},
email: {
name: "email",
type: "email",
value: "jbloggs#test.com"
}
}
You can send the type within the value or the name.
In your php you can use explode to separate the type from the value/name. Here's how to send it within the value.
$('#form').on('submit', function(e) {
e.preventDefault();
var fields = e.serializeArray();
for(var i = 0; i < fields.length; i++){
var item = e.find(':input').eq(i);
var fieldType = item.attr("type") === null ? item.prop("tagName") : item.attr("type");
fieldType = fieldType === null ? item.prop("tagName") : fieldType;
data.push({"name": fields[i].name, "value": fieldType + "|" + fields[i].value })
}
$.post('ajax/forms.ajax.php', {
data: data
}, function(r) {
var json = JSON.parse(r);
}
});

JavaScript form validation not working as intended

Good morning,
I'm working on some simple form validation. Whenever I submit my form, the error message appears, but I can repeatedly spam the button for numerous error messages. Is there a way I can change this to only show the error message once? I've also noticed that even if I populate both fields it will still flash quickly in my console with the error log but not show the error.
Can anyone tell me what I'm doing wrong here?
var uname = document.forms['signIn']['userame'].value;
var pword = document.forms['signIn']['password'].value;
function validateMe (e) {
if (uname.length || pword.length < 1 || '') {
var container = document.getElementById('error-container');
var errorMsg = document.createElement('div');
errorMsg.className = 'error-message';
errorMsg.innerHTML = '<span class="heading-large">Please enter a valid username or password</span>';
container.appendChild(errorMsg);
console.log('An error occured');
return false;
}
}
<form id="signIn" action='#'>
<div class="boxed left-floater">
<h1 class="heading-large margin-top">Sign in</h1>
<div id="error-container"></div>
<div class="form-group">
<label class="form-label-bold" for="username">Username</label>
<input class="form-control log-in-form-control" id="username" name="username" type="text">
</div>
<div class="form-group">
<label class="form-label-bold" for="password">Password</label>
<input class="form-control log-in-form-control" id="password" type="password" name="password">
</div>
<div>
<a class="right-floater forgotten-password" href="forgottenpassword.html">Forgotten Password</a>
<button class="button clear right-floater" type="submit" onclick="validateMe();">Sign In</button>
</div>
</div>
</form>
Fiddle
You must be clearing the contents of your container to avoid duplication of elements. Below are few things to note:
You were trying to get userame instead of username in your fiddle. May be spelling mistake.
Keep input type=submit instead of button
Pass the event to your validateMe function to prevent the default action of post.
Move the variables within the function to get the actual value all the time
function validateMe(e) {
e.preventDefault();
var uname = document.forms['signIn']['username'].value;
var pword = document.forms['signIn']['password'].value;
var container = document.getElementById('error-container');
container.innerHTML = ''; //Clear the contents instead of repeating it
if (uname.length < 1 || pword.length < 1) {
var errorMsg = document.createElement('div');
errorMsg.className = 'error-message';
errorMsg.innerHTML = '<span class="heading-large">Please enter a valid username or password</span>';
container.appendChild(errorMsg);
console.log('An error occured');
return false;
}
}
<form id="signIn" action='#'>
<div class="boxed left-floater">
<h1 class="heading-large margin-top">Sign in</h1>
<div id="error-container"></div>
<div class="form-group">
<label class="form-label-bold" for="username">Username</label>
<input class="form-control log-in-form-control" id="username" name="username" type="text">
</div>
<div class="form-group">
<label class="form-label-bold" for="password">Password</label>
<input class="form-control log-in-form-control" id="password" type="password" name="password">
</div>
<div>
<a class="right-floater forgotten-password" href="forgottenpassword.html">Forgotten Password</a>
<input value="Sign In" class="button clear right-floater" type="submit" onclick="validateMe(event);" />
</div>
</div>
</form>
Updated Fiddle
Edit - if condition was failing and have updated it accordingly
this is full work code
var uname = "";
var pword = "";
function validateMe(e) {
e.preventDefault();
uname = document.forms['signIn']['username'].value;
pword = document.forms['signIn']['password'].value;
if (uname.length || pword.length < 1 || '') {
var container = document.getElementById('error-container');
var errorMsg = document.createElement('div');
errorMsg.className = 'error-message';
errorMsg.innerHTML = '<span class="heading-large">Please enter a valid username or password</span>';
container.appendChild(errorMsg);
console.log('An error occured');
return false;
}
return true;
}
<form id="signIn">
<div class="boxed left-floater">
<h1 class="heading-large margin-top">Sign in</h1>
<div id="error-container"></div>
<div class="form-group">
<label class="form-label-bold" for="username">Username</label>
<input class="form-control log-in-form-control" id="username" name="username" type="text">
</div>
<div class="form-group">
<label class="form-label-bold" for="password">Password</label>
<input class="form-control log-in-form-control" id="password" type="password" name="password">
</div>
<div>
<a class="right-floater forgotten-password" href="forgottenpassword.html">Forgotten Password</a>
<button class="button clear right-floater" type="submit" onclick="validateMe(event);">Sign In</button>
</div>
</div>
</form>

jQuery keep other boxes not edited state

In the code below when I click edit the other boxes loose the edited icon until cancel is clicked.
Is there away that I can have it so that if a box is not being edited it keeps the normal state of code?
The library I am using is: https://vitalets.github.io/x-editable/
Normal State:
When an edit button is clicked:
jQuery:
/* X-Editable */
$(function(){
$.fn.editable.defaults.mode = 'inline';
$.fn.editable.defaults.params = function (params) {
params._token = $("#_token").data("token");
return params;
};
var dataURL = $('.updateField').data('url');
var inputName = $('.updateField').attr("name");
$('.updateField').editable({
type: 'text',
url: dataURL,
name: inputName,
placement: 'top',
title: 'Enter public name',
toggle:'manual',
send:'always',
ajaxOptions:{
dataType: 'json'
}
});
$('.edit').click(function(e){
var container = $(this).closest('.input-group'); // !!
var input = container.find('.updateField');
var inputName = input.attr('name');
var dataURL = input.data('url');
console.log(inputName);
e.stopPropagation();
container.find('.updateField').editable('toggle'); // !!
container.find('.edit').hide(); // !!
});
$(document).on('click', '.editable-cancel, .editable-submit', function(e){
$(e.target).closest('.input-group').find('.edit').show(); // !!
})
//ajax emulation. Type "err" to see error message
$.mockjax({
url: '/post',
responseTime: 100,
response: function(settings) {
if(settings.data.value == 'err') {
this.status = 500;
this.responseText = 'Validation error!';
} else {
this.responseText = '';
}
}
});
});
Normal State HTML:
<input name="__RequestVerificationToken" type="hidden" value="{{ csrf_token() }}" />
<div class="box-body">
<div class="form-group">
<label class="col-sm-2 control-label" for="siteName">Website Name</label>
<div class="col-sm-3">
<div class="input-group">
<input class="form-control updateField" data-url="{{ route('generalDataSubmit', 1)}}" data-title="Website Name" name="siteName" placeholder="Email" type="input" value="{{ old('siteName', $siteSettingsData->siteName)}}"> <span class="input-group-btn"><button class="btn btn-default edit" type="button"><span class="glyphicon glyphicon glyphicon-pencil"></span></button></span>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="siteEmail">Website E-Mail Address</label>
<div class="col-sm-3">
<div class="input-group">
<input class="form-control updateField" data-url="{{ route('generalDataSubmit', 1) }}"data-title="Website E-Mail Address" name="siteEmail" placeholder="Site E-Mail" type="email" value="{{ old('siteEmail', $siteSettingsData->siteEmail) }}"> <span class="input-group-btn"><button class="btn btn-default edit" type="button"><span class="glyphicon glyphicon glyphicon-pencil"></span></button></span>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="siteCopyright">Website Copyright</label>
<div class="col-sm-3">
<div class="input-group">
<input class="form-control updateField" data-url="{{ route('generalDataSubmit', 1)}}" data-title="Website Copyright" name="siteCopyright" placeholder="Site Copyright" type="input" value="{{ old('siteCopyright', $siteSettingsData->siteCopyright)}}"> <span class="input-group-btn"><button class="btn btn-default edit" type="button"><span class="glyphicon glyphicon glyphicon-pencil"></span></button></span>
</div>
</div>
</div>
</div>
<!-- /.box-body -->
try changing the following line:
container.find('.edit').hide();
to
$(this).hide();
It seems like you are using some bootstrap design template.From my point of view the code
$('.edit').click(function(e){
var container = $(this).closest('.input-group'); // !!
var input = container.find('.updateField');
var inputName = input.attr('name');
var dataURL = input.data('url');
console.log(inputName);
e.stopPropagation();
container.find('.updateField').editable('toggle'); // !!
container.find('.edit').hide(); // !!
});
seems ok.I don't understand the line container.find('.updateField').editable('toggle'); // !! in the function.Are you using some kind of library. My suggestion is to remove that line from your code and test.Also check whether you are getting the correct value of inputName outputted.And finally check in the console for any errors when you click the edit button.
Try using $(e) instead of $(this) in the following code:
$('.edit').click(function(e){
//var container = $(this).closest('.input-group');
var container = $(e).closest('.input-group');
var input = container.find('.updateField');
var inputName = input.attr('name');
var dataURL = input.data('url');
console.log(inputName);
e.stopPropagation();
container.find('.updateField').editable('toggle'); // !!
container.find('.edit').hide(); // !!
});

Generate dynamic form input fields and collect field data in an array in angularJS

I need to generate form input fields dynamically by clicking 'add sale' button on the form. which is accomplished
Also on change selected drop down, it get the price from the database and use the quantity to calculate the amount of that product.
if I click on 'add sale' button for another form generate the changes affect the previous one.
how to calculate the amount for each form independently and collect the data in it using angularJS?
this is controller
appcat.controller("MainCtrl", ['$scope', '$http', '$location', function ($scope, $http, $location)
{
//var quan = $scope.quantity;
$http.get('/api/pproduct').success(function (data)
{
$scope.pcategoryA = data;
});
// this controll the addition and removal
$scope.choices = [{ id: 'choice1' }];
//any time changes occurr it calculate the Amount
$scope.changedValue = function (item,quan)
{
if (item != null && quan !=null)
{
$http.get('/api/product/'+ item).success(function (data) // this is the price for that product from the Database
{
//this sets amount field
$scope.amount = parseFloat(data.price * quan);
});
}
}
// this generate a form
$scope.addNewChoice = function ()
{
var newItemNo = $scope.choices.length + 1;
$scope.choices.push({ 'id': 'choice' + newItemNo });
};
// this remove the form
$scope.removeChoice = function () {
var lastItem = $scope.choices.length - 1;
if ($scope.choices.length > 1) {
$scope.choices.splice(lastItem);
}
};
}]);
this is the html
<form class="form-inline" role="form" padding-left:10em">
<strong class="error">{{ error }}</strong>
<div class="form-group">
<label for="name">
Invoice No. :
</label>
<input type="text" class="form-control" id="name" ng-model="name" />
</div>
<br /><hr />
<div ng-controller="MainCtrl">
<fieldset data-ng-repeat="choice in choices">
<div class="form-group">
<label for="name">
Quantity :
</label>
<input type="text" class="form-control" id="quantity" ng-model="quantity" />
</div>
<div class="form-group">
<div class="form-group">
<label class="control-label"> Product : </label>
<select class="form-control" id="selected_id" ng-model="selected_id" ng-options="c.Value as c.Text for c in pcategoryA"
ng-change="changedValue(selected_id,quantity)">
<option value="">-- Select Category --</option>
</select>
</div>
</div>
<div class="form-group">
<label for="name">
Amount :
</label>
<input type="text" class="form-control" id="amount" ng-model="amount" ng-readonly="true" />
</div>
<button class="remove" ng-show="$last" ng-click="removeChoice()">-</button>
<br />
<hr />
</fieldset>
<button type="submit" class="col-sm-offset-10 addfields" ng-click="addNewChoice()">
Add Sale
</button>
</div>
</form>
thanks in advanced!!
You have to put 'amount' in choices array.
$scope.choices = [{ id: 'choice1', amount: 0}];
Then in controller:
$scope.changedValue = function (choise,item,quan)
choise.amount = parseFloat(data.price * quan);
And in tempalte:
ng-change="changedValue(choise,selected_id,quantity)">
<input type="text" class="form-control" id="amount" ng-model="choise.amount" ng-readonly="true" />

Username checking not working for form with multiple register models (mvc)

I have a page which allows an admin to add multiple users to the database at once, with usernames and passwords. I use remote username checking, so in my account models I have this:
public class RegisterModel
{
[Required]
[Display(Name = "User name")]
[System.Web.Mvc.Remote("doesUserNameExist", "Account", HttpMethod = "POST", ErrorMessage = "User name already exists. Please enter a different user name.")]
public string UserName { get; set; }
// ...etc
}
In my account controller I have this:
[HttpPost]
public JsonResult doesUserNameExist(string UserName)
{
var user = Membership.GetUser(UserName);
return Json(user == null);
}
Now this works nicely on a single form, with one user being created, using the mvc html helpers. The message saying that a username is in use shows up as I'm typing it into the field. But on this form which doesn't use the mvc helpers, instead pure html and javascript, it doesn't show up:
#model List<PicsWebApp.Models.UserRegisterModel>
#{
ViewBag.Title = "NewRep";
}
<div class="col-lg-12">
<h1>First-Time Setup</h1>
</div>
<legend></legend>
<div class="col-lg-12">
<h3>Add Representatives <small>You can add more representatives later</small></h3>
#using (Html.BeginForm("NewRep", "Admin", new { jobid = ViewData["jobid"] }, FormMethod.Post, new { #class = "form" }))
{
#Html.ValidationSummary(true)
<p>
Skip
<input type="submit" class="btn btn-primary" />
<button type="button" class="btn btn-default" id="add">Add Rep</button>
</p>
<div id="fieldform" class="col-lg-12">
<div id="container0" class="col-lg-4" style="background-color: #eee; border: 4px solid white;">
<h4 style="text-align: center">New Rep</h4>
<div class="form-group">
<label>Representative Name</label><input type="text" class="form-control" name="models[0].RepName" />
</div>
<div class="form-group">
<label>Contact Number</label><input type="text" class="form-control" name="models[0].ContactNumber" />
</div>
<div class="form-group">
<label>Rep Username</label><input type="text" class="form-control" name="models[0].UserName" />
<input class="text-box single-line" data-val="true" data-val-remote="User name already exists. Please enter a different user name." data-val-remote-additionalfields="*.UserName" data-val-remote-type="POST" data-val-remote-url="/Account/doesUserNameExist" data-val-required="The User name field is required." id="UserName" name="models[0].UserName" type="text">
<span class="field-validation-valid" data-valmsg-for="UserName" data-valmsg-replace="true"></span>
</div>
<div class="form-group">
<label>Location</label><select id="select-0" class="form-control" name="models[0].Location"></select>
</div>
<div class="form-group">
<label>Rep Password</label><input type="password" class="form-control" name="models[0].Password" />
</div>
<div class="form-group">
<label>Confirm Password</label><input type="password" class="form-control" name="models[0].ConfirmPassword" />
</div>
</div>
</div>
}
</div>
<script src="https://code.jquery.com/jquery.js"></script>
<script type="text/javascript">
var selectValues = {
"Johannesburg": "Johannesburg",
"Pretoria": "Pretoria",
"Cape Town": "Cape Town",
"Pretoria": "Pretoria",
"Durban": "Durban",
"Centurion": "Centurion"
};
$.each(selectValues, function (key, value) {
$('select')
.append($('<option>', { value: key })
.text(value))
.prop("selectedIndex", -1);
});
var i = 1;
$("#add").click(function () {
var inputfield = '<div class="col-lg-4" id="' + container + i + '" style="background-color: #eee; border: 4px solid white;"><h4 style="text-align: center">New Rep</h4><div class="form-group"><label>Representative Name</label><input type="text" class="form-control" name="models[' + i + '].RepName" /></div>' +
'<div class="form-group"><label>Contact Number</label><input type="text" class="form-control" name="models[' + i + '].ContactNumber" /></div>' +
'<div class="form-group"><label>Rep Username</label><input type="text" class="form-control" name="models[' + i + '].UserName" /></div>' +
'<div class="form-group"><label>Location</label><select id="select-' + i + '" class="form-control" name="models[' + i + '].Location"></select></div>' +
'<div class="form-group"><label>Rep Password</label><input type="password" class="form-control" name="models[' + i + '].Password" /></div>' +
'<div class="form-group"><label>Confirm Password</label><input type="password" class="form-control" name="models[' + i + '].ConfirmPassword"/></div></div>'
$('#fieldform').append(inputfield)
$.each(selectValues, function (key, value) {
$('#select-' + i)
.append($('<option>', { value: key })
.text(value))
.prop("selectedIndex", -1);
});
i++
});
</script>
I understand I would have to add validation attributes to the username input fields but I tried that and it still didn't work. Any ideas?
You could validate in your controller (when the ajax request is sent) using the Validator class. This class allows you to call Validator.TryValidateObject to validate your model's data annotations such as [Required].
Then once this has passed/failed return the constructed json data with success/error messages.
Here is the article that really helped me on this:
http://odetocode.com/blogs/scott/archive/2011/06/29/manual-validation-with-data-annotations.aspx

Categories