Validating a form with a dynamic name inside directive - javascript

<form name="{{ formname }}" novalidate>
<input type="text" ng-model="first_name" required>
<input type="text" ng-model="last_name" required>
<input type="text" ng-model="email" required>
<span class="error" ng-show="formname.$invalid">Fill in required fields.</span>
<button type="submit"></button>
</form>
I'm trying to validate the form using Angular's built in validation but because the formname is set dynamically by text passed in from the scope I'm not sure how to call it. This attempt above doesn't work.

You can do it with a little help from the controller. Define another variable (f in the example below), watch formname and update f accordingly:
.controller("...", function($scope) {
$scope.first_name = "";
$scope.formname = "fff";
$scope.f = null;
$scope.$watch("formname",function(newval,oldval,scope) {
scope.f = scope[newval];
});
});
See fiddle: http://jsfiddle.net/T7vuD/

Related

`Required` attribute not working with <form> tag [duplicate]

This question already has answers here:
HTML5 required attribute not working
(2 answers)
Closed last month.
My required attribute doesn't specify that an input field must be filled out before submitting the form.
HTML:
<!-- Modal Content -->
<form class="modal-content2">
<div class="container3">
<h1>Sign Up</h1>
<p>Please fill in this form to create an account.</p>
<hr>
<label for="firstName"><b>First Name</b></label>
<input type="text" id="firstName" placeholder="Enter First Name" name="firstName" required>
<label for="lastName"><b>Last Name</b></label>
<input type="text" id="lastName" placeholder="Enter Last Name" name="lastName" required>
<label for="username"><b>Username</b></label>
<input type="text" id="username" placeholder="Enter Username" name="username" required>
<label for="email"><b>Email</b></label>
<input type="text" id="email" placeholder="Enter Email" name="email" required>
<label for="psw"><b>Password</b></label>
<input type="password" id="password" placeholder="Enter Password" name="psw" onfocus="this.value=''"
required>
<label for="psw-confirm"><b>Confirm Password</b></label>
<input type="password" id="cfmpassword" placeholder="Confirm Password" name="psw-confirm" onfocus="this.value=''"
required>
<br>
<br>
<p>By creating an account you agree to our <a href="aboutus.html" style="color:dodgerblue">Terms &
Privacy</a>.</p>
<div class="clearfix">
<button type="button" onclick="document.getElementById('id02').style.display='none'" class="cancelbtn2">Cancel</button>
<button type="button" class="signupbtn" onclick="signUp()">Sign Up</button>
</div>
</div>
</form>
JavaScript:
function signUp() {
if (document.getElementById("password").value == document.getElementById("cfmpassword").value) {
var users = new Object();
users.firstName = document.getElementById("firstName").value;
users.lastName = document.getElementById("lastName").value;
users.username = document.getElementById("username").value;
users.email = document.getElementById("email").value;
users.password = document.getElementById("password").value;
var postUser = new XMLHttpRequest(); // new HttpRequest instance to send user details
postUser.open("POST", "/users", true);
postUser.setRequestHeader("Content-Type", "application/json");
postUser.send(JSON.stringify(users));
//go to the logged in page
window.location = "main.html";
}
else {
alert("Password column and Confirm Password column doesn't match!")
}
}
As the required attribute does not work, users can continuously submit empty forms and those will be stored in my SQL database
I don't have a <button type="submit"> in the form as this prevents me from using windows.location.
I am new to programming, can someone please give some suggestions (with explanations) on what to do to fix this? Any help would be appreciated! Thanks a lot! (I am using vanilla JavaScript for this)
The required attribute does not work because your form is not submitted. You need to specify a button with a type="submit" or <input type="submit"> to submit your form.
I suggest you to move the signUp function inside the form tag like this with an onsubmit event:
<form onsubmit="signUp(event)">.
Then add this to you Javascript function:
function signUp(event) {
event.preventDefault();
... your old code
}
For me, I see a number of possible issues. I have tried to remove them with the following sample code. I am assuming that /users will return something useful for checking and alerting the member if there is an error with the accessing of /users or the processing of the data.
The use of the required attribute of <input> will do nothing obvious in your code as the <button> has an onclick=signUp() call which will triggered before the browser check. With your current code the form values (present or not) will still be sent to /users as there is no testing for those values.
You need to move the signUp() call to the <form> if you want the browser check to be run.
To test this, removing the onclick=signUp() in the <button> will show you a browser tip window saying the value is needed.
As you are insisting on using AJAX to post the form data, moving the check to the <form> submit is idea and personally, I would still be checking the values - just good practice.
The next issue is you are not waiting for the return of a success or fail response from /users. In fact, you are blindly redirecting to main.html. If there is an error, the user will never know. This is a very bad user experience.
This is corrected in the sample code by checking for a response with a call-back, checking that response value and then alerting the member or redirecting if there is no error.
var users = {};
function ajaxPost(url,postData,callFunc) {
var http = new XMLHttpRequest();
if(! http){
return false;
}
http.onreadystatechange=function(){
if((http.readyState == 4) && (http.status == 200)) {
if(callFunc){
callFunc(http.responseText);
}
}
}
http.open('POST',url,true);
http.send(postData);
}
function validResult(str) {
if (str == "valid") {
// go to the logged in page
window.location = "main.html";
} else {
console.log("invalid result, let the user know");
}
}
function signUp(e) {
if(e){e.stopPropagation();e.preventDefault();}
var d = document.getElementById("signupForm").querySelectorAll("input");
var i, max = d.length;
// Quick check for values only. No check for the format of the values.
// This is good practice as a browser may still ignore the `required`
// attribute.
for(i=0;i<max;i++) {
d[i].value = d[i].value.trim();
if (d[i].value) {
users[d[i].name] = d[i].value;
} else {
// An alert would be better for the user here.
console.log("Missing value for ["+ d[i].name +"]");
// Go no further if there is a missing value.
return;
}
}
// at this point, all values added to the users object.
console.log("users:["+ JSON.stringify(users) +"]");
// Send the data and wait for a return value from /users
// --- remove comment on the following line to post ----
//ajaxPost("/users",JSON.stringify(users),validResult);
}
window.onload = function(){
var c = document.getElementById("signupForm");
if (c) {
c.addEventListener("submit",signUp,false);
}
}
<form id="signupForm">
<label for="firstName"><b>First Name</b></label>
<input type="text" id="firstName" placeholder="Enter First Name" name="firstName" required>
<p>
<label for="email"><b>Email</b></label>
<input type="email" id="email" placeholder="Enter Email" name="email" required>
<p>
<button id="submit" type="submit">Check and submit</button>
</form>
Basic of HTML5 validation. You have it on button click and that runs before the validation happens. This shows you that the onclick runs and the onsubmit does not. Use the correct event.
function loginSubmit () {
console.log('loginSubmit')
}
function loginClick () {
console.log('loginClick')
}
<form onsubmit="loginSubmit()">
<input name="foo" required />
<button onclick="loginClick()">click</button>
</form>
The way required attribute works is it determines whether the element its assigned to has a value length higher than a zero, if that statement is false (meaning the value length of zero) then upon submitting the form it focuses that element as its "required" to be fulfilled.
Here is an example with JavaScript and how checking input fields could work inside it.
const form = document.querySelector('form[action="signup.php"]'); // Form
const inputs = form.querySelectorAll('input'); // All input elements inside the form
const submit = form.querySelector('button[type="submit"]'); // Submit button inside the form
// Add onclick event to the form button
submit.addEventListener('click', function(event) {
event.preventDefault(); // This prevents the button from submitting the form the traditional way
submit_form(); // but instead our way
});
function submit_form()
{
// We iterate through the form input elements
for (var i = 0; i < inputs.length; i++)
{
// We check if the current element has
// the attribute required and if so
// we proceed with checks
if (inputs[i].hasAttribute('required') && inputs[i].value.length == 0)
{
inputs[i].focus(); // We focus on the required element
alert(inputs[i].placeholder+' is required!'); // Alert the user that the element is required
break; // Break from the loop
}
else
{
if (i == (inputs.length - 1)) form.submit(); // If the loop's i variable counter hits the same value as the
// input elements length then it means all fields are filled
}
}
}
form {
width:300px;
margin:auto
}
form button,
form input {
width:100%;
height:48px;
padding:0 15px;
font-size:18px;
box-sizing:border-box;
}
form input:focus {
background-color:#f2dfb7;
}
<form action="signup.php" method="POST">
<input type="text" name="first_name" placeholder="First Name" required>
<input type="text" name="last_name" placeholder="Last Name" required>
<input type="email" name="email" placeholder="Email Address" required>
<input type="email" name="email_repeat" placeholder="Email Address (Repeat)" required>
<input type="password" name="password" placeholder="Password" required>
<input type="text" name="phone" placeholder="Phone Number" required>
<input type="text" name="birthday" placeholder="Birthday (MM/DD/YYYY)" required>
<button type="submit">Sign Up</button>
</form>

ng-form inside ng-repeat not updating subform.$submitted

I am trying create forms inside ng-repeat, everything is working fine except submit button. Submit button placed in main form it is common for all sub forms.
If the submit button is clicked mainForm.$submitted gets updated but userForm.$submitted dose not changing. Is there any work around for that ?
angular.module("sampleApp", [])
.controller('sampleCtrl', function($scope) {
$scope.users = [{},{}];
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.js"></script>
<div ng-app="sampleApp" ng-controller="sampleCtrl">
<form name="mainForm" novalidate>
<input type="text" name="school" ng-model="school" required>
main form input valid=>{{mainForm.school.$valid}}
<div ng-repeat="user in users">
<ng-form name="userForm">
<input type="text" ng-model="user.name" name="name" required>
sub form input valid=>{{userForm.name.$valid}} | sub form submit=>{{userForm.$submitted}}
</ng-form>
</div>
<button type="submit">Submit</button>
Form valid=>{{mainForm.$valid}} | Main From submit => {{mainForm.$submitted}}
</form>
</div>
Intro
So, I added a ng-click handler to the button so that you set the submitted status of the internal form as well.
The only difficult I had was to actually get the form reference, but I added the function $scope.setUserForm which is called with an ng-init. The solution pattern is from: https://stackoverflow.com/a/23862411/1688441
Also, please keep in mind you need an array of userForms to keep the references. On click you iterate through these elements and set the submitted.
Code
angular.module("sampleApp", [])
.controller('sampleCtrl', function($scope) {
$scope.UserForms = [];
$scope.setUserForm = function(form) {
$scope.UserForm = form;
$scope.UserForms.push(form);
}
$scope.forms = {};
$scope.users = [{}, {}];
$scope.handleClick = function() {
$scope.UserForms.forEach(function(element) {
element.$submitted = true;
});
};
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.js"></script>
<div ng-app="sampleApp" ng-controller="sampleCtrl">
<form name="mainForm" novalidate>
<input type="text" name="school" ng-model="school" required>
input valid=>{{mainForm.school.$valid}}
<div ng-repeat="user in users">
<ng-form name="userForm">
<div ng-init="setUserForm(userForm);"></div>
<input type="text" ng-model="user.name" name="name" required>
input valid=>{{userForm.name.$valid}} | form submit=>{{userForm.$submitted}}
</ng-form>
</div>
<button type="submit" ng-click="handleClick()">Submit</button>
Form valid=>{{mainForm.$valid}} | From submit => {{mainForm.$submitted}}
</form>
</div>

Angular Validation not working when dot in model

Angular validation is working when there is no dot(.) in model in this following code...
<div class="form-group">
<label for="title">Post Title</label>
<input ng-model="new_title" class="form-control" name="new_title" type="text" required/>
<p class="error" ng-show="addForm.new_title.$touched && addForm.new_title.$invalid">This field is required</p>
</div>
But it is not working when I use ng-model="new.title" like in the following code...
<div class="form-group">
<label for="title">Post Title</label>
<input ng-model="new.title" class="form-control" name="new.title" type="text" required/>
<p class="error" ng-show="addForm.new_title.$touched && addForm.new.title.$invalid">This field is required</p>
</div>
Here is what I am using new in my controller
$scope.submit = function(){
var request = CRUD.create($scope.new);
request.success(function(response){
$scope.flash = response.status;
});
};
Help would be appreciated
You should not change your name along with your model.
<div class="form-group">
<label for="title">Post Title</label>
<input ng-model="new.title" class="form-control" name="new_title" type="text" required/>
<p class="error" ng-show="addForm.new_title.$touched && addForm.new_title.$invalid">This field is required</p>
</div>
This is how it should look like.
The validation doesn't check your model. It checks the form model that you bind the scope when using name attribute. So when checking for errors, you use the name attributes of the form and the inputs. You just need to change your name of the input from new.title to new_title.
You can't use dot (.) in variable name. you should use _ or camel-case to declare variable like:
new_title or newTitle
if want to use dot (.) notation then use like
var info = {
title: "your title"
}
then you can use like
<input ng-model="info.title" class="form-control" name="info.title" type="text" required/>
but you cant use new as a variable name. new is a reserved keyword

How to check if the required attribute is set on a field

I have a simple form that has some required fields in it.
<form name="form" method="post">
<pre>
<label> Name: </label><input type="text" name="name" required>
<label> Address: </label><input type="text" name="add" required>
<label>Telephone: </label><input type="text" name="tel">
<input type="submit" value="Submit Form">
</pre>
</form>
I know you can set the required attribute using document.forms['form']['name'].required = false. But is there a way where you can just check if the required attribute is set or not? I tried using getattribute() but it just returns blank. I also tried using the code below, but it always executes the statement, even if the required attribute isn't set (e.g. on the telephone field).
if( document.forms['form']['name'].required = true)
label.innerHTML += " (required)"
Does anyone know of a way I can do this?
Update: Both setting the if statement to == instead of = and using hasAttribute work, thanks.
Try this :
var elem = document.getElementsByTagName('input')[0];
if(elem.hasAttribute('required')){
//do your stuff
}

Determining if a form is valid using angular

I'm trying to determine if a form is valid or not using angular.
I have a form like this:
<form name="form" novalidate>
<p>
<label>Number: </label>
<input type="number" min="0" max="10" ng-model="test.number" required />
</p>
<p>
<label>Name: </label>
<input type="text" ng-model="test.name" required />
</p>
<button ng-click="sendTest(test)">Submit</button>
</form>
And, on the sendTest function I did:
angular.module('demo', [
]).controller('MainCtrl', function($scope){
$scope.test = {
name: 'das'
};
$scope.sendTest = function(test) {
console.log(form.$valid);
console.log(test.$valid);
}
});
The problem is that both form.$valid and test.$valid are undefined. I tried to do this following these examples:
http://dailyjs.com/2013/06/06/angularjs-7/
http://www.youtube.com/watch?v=J82OD76QhPo
Here's the complete code for this demo:
http://plnkr.co/edit/l0E62KPJu4Z2r15VNjJq
form gets added to the scope, try: console.log($scope.form.$valid)
BTW, it's called form because that's the value you have specified on the form tag's name attribute. You can also add name attributes to the input fields if you from your controller want to know the state of the specific fields.
Example: http://plnkr.co/edit/Ra98yIFYso94flDIqNCD?p=preview

Categories

Resources