Prevent Form Submit if Phone Number is Invalid - Angularjs - angularjs

I am wanting to prevent form submission if the phone input is invalid per my ng-pattern WITHOUT using disabled on the button. I have tried adding logic to my submitForm function to no avail. Something along the lines of...
Adding a validation function to my angular code:
const validPhone = function (phone) {
var re = /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/;
return re.test(phone);
}
And adding some logic to my submit function like...
if (!this.validPhone(main.contact.phone)) {
$window.alert("Please a valid phone number!");
return false;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script>
(function () {
"use strict";
angular.module("rzApp", []).controller("MainCtrl", MainCtrl); // as main.
function MainCtrl($document, $timeout, $window) {
var main = this;
main.now = new Date();
main.contact = {
phone: "##phone##",
company: "##company##"
};
main.submitForm = _submitForm;
function _submitForm() {
if (!main.contact.phone) {
$window.alert("Please enter your phone number!");
return false;
}
if (!main.contact.company) {
$window.alert("Please enter your company!");
return false;
}
$timeout(function () {
$document[0].forms[0].submit();
}, 0);
}
}
})();
</script>
<form method="post" id="f" novalidate name="mainForm">
<div class="input-field">
<input type="text" placeholder="Phone *" value="##phone##" name="phone"
ng-model="main.contact.phone" required
style="margin-bottom: 0; margin-top: 16px"
ng-pattern="/^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/im" />
<small class="form-text rz-error" ng-show="mainForm.phone.$error.required">This
field is
required.</small>
<small class="form-text rz-error" ng-show="mainForm.phone.$error.pattern">
Doesn't look like a valid phone number!</small>
</div>
<div class="input-field">
<input type="text" placeholder="Company *" name="company"
ng-model="main.contact.company" value="##company##" required
style="margin-bottom: 0; margin-top: 16px" />
<small class="form-text rz-error"
ng-show="mainForm.company.$error.required">This field is
required.</small>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="callback_request"
value="yes" style="margin-bottom: 0; margin-top: 16px" />
<label class="form-check-label" for="flexCheckDefault">
I would like a call & a free audit.
</label>
</div>
<div class="input-field">
<input type="submit" class="button alt" value="Download Now"
ng-click="main.submitForm()" style="margin-bottom: 0; margin-top: 16px" />
</div>
<div style="margin-top: 10px">
<small><em class="text-muted">* Denotes a required field.</em></small>
</div>
</form>

Do something like:
<form (keydown.enter)="validateFunction($event)"></form>
Then put your logic in validate function and do $event.preventDefault() if needed.

I removed the disabled from the button and added logic to check for a valid phone number to my angular.js code:
<script>
(function () {
"use strict";
angular.module("rzApp", []).controller("MainCtrl", MainCtrl); // as main.
function MainCtrl($document, $timeout, $window) {
var main = this;
main.now = new Date();
main.contact = {
phone: "##phone##",
company: "##company##"
};
main.submitForm = _submitForm;
main.validPhone = _validPhone;
function _submitForm() {
if (!main.validPhone(main.contact.phone)) {
$window.alert("Please enter a valid phone number!");
return false;
}
if (!main.contact.company) {
$window.alert("Please enter your company!");
return false;
}
$timeout(function () {
$document[0].forms[0].submit();
}, 0);
}
function _validPhone(phone) {
const re =
/^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/;
return re.test(phone);
}
}
})();
</script>

Related

angularjs - Update ng-model value from controller?

View 1:
<div ng-controller="ctrl1">
<button ng-click="goToExtendedForm({'name':'aaa'})">
</button>
</div>
ctrl1:
$scope.selectedList = {
name: ""
};
$scope.goToForm = function(e) {
$scope.selectedList.name = e.name;
$state.go('view2');
console.log(e); // prints updated value
};
View 2:
<div ng-controller="ctrl1">
<input
id="name"
name="name"
type="text"
ng-model="selectedList.name"
ng-readonly="true"
/>
</div>
But the input box is always empty, even though to get to the view the goToForm() is called. Why doesn't it update the HTML value?
Views are changed with ui.router's $state.
From your description, your code is supposed to work. Check if you are passing the right parameter into the function. Here is a working demo:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.selectedList = {
name: ""
};
$scope.goToForm = function(e) {
$scope.selectedList.name = e.name;
console.log(e); // prints updated value
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<button ng-click="goToForm({'name':'aaa'})">Change</button>
<br>
<input type="text" ng-model="selectedList.name" ng-readonly="true" />
</div>
Try adding $scope.$apply() at the end of your $scope.goToForm function
Try this ;
HTML Code
<div ng-app>
<div ng-controller="ClickToEditCtrl">
<input
id="name"
name="name"
type="text"
ng-model="selectedList.name"
ng-readonly="true"
/>
<button ng-click="goToForm(testUserDetails)" >Go To</button>
</button>
</div>
</div>
Define controller like this;
function ClickToEditCtrl($scope) {
$scope.selectedList = {
name: ""
};
$scope.testUserDetails ={
name: "nimal"
}
$scope.goToForm = function(e) {
$scope.selectedList.name = e.name;
console.log(e); // prints updated value
};
}

ng-show not watching variable change

I have a progress bar I want to show after I click a button.
I set my variable to true on click, yet it's not working.
The ng-show in question is on the bottom of the html, and the button i click is on a different html page but i didn't include because it uses the successOnClick function in this same controller. I console logged the isEmailing variable inside the onclick and it is assigned true. Doesn't work for ng-if either
What gives?
module.exports = app => {
app.controller('ContactController', ($scope, $http) => {
$scope.isEmailing = false;
$scope.email = (e) => {
$scope.isEmailing = true;
const requestBody = {};
const id = e.target.id;
requestBody.name = document.getElementById(`${id}-name`).value;
requestBody.email = document.getElementById(`${id}-email`).value;
requestBody.subject = document.getElementById(`${id}-subject`).value;
requestBody.body = document.getElementById(`${id}-body`).value;
$http.post('/email', JSON.stringify(requestBody), {
'Content-Type': 'application/json'
})
.then(res => {
console.log('Success!');
document.getElementById(`${id}-name`).value = '';
document.getElementById(`${id}-email`).value = '';
document.getElementById(`${id}-subject`).value = '';
document.getElementById(`${id}-body`).value = '';
$scope.isEmailing = false;
})
.catch(err => {
console.log('Error!');
$scope.isEmailing = false;
})
}
$scope.successOnClick = () => {
$scope.isEmailing = true;
}
})
}
<footer class="footer" ng-controller="ContactController">
<div class="footer__block social-media-container">
<div class="social-media">
<img src="http://i.imgur.com/bVqv5Kk.png" alt="fb-icon">
<img src="http://i.imgur.com/sJWiCHV.png" alt="twitter-icon">
<img src="http://i.imgur.com/o7yTVyL.png" alt="insta-icon">
</div>
</div>
<div class="footer__block">
<form class="footer__form" ng-submit="email($event)" id="footer">
<textarea placeholder="Message" id="footer-body" required></textarea>
<input type="text" placeholder="Name" id="footer-name" required>
<input type="email" placeholder="Email" id="footer-email" required>
<input type="text" placeholder="Subject" id="footer-subject" required>
<input type="submit" placeholder="Email">
</form>
</div>
<div class="footer__block mailing-list">
<span>Join our Mailing List!</span>
<form>
<input type="email" placeholder="Email" required>
<input type="submit">
</form>
</div>
<!-- <div class="grey-screen">
<div class="success">
<h1>Success!</h1>
</div>
</div> -->
<div class="progress-bar" ng-show="isEmailing">
</div>
</footer>
If you have several controller of same type it is not mean, that they all are same the instance. AngularJS creates controllers not via singleton pattern. You should synchronize them by yourself by means of events:
angular.module('app', [])
.controller('MyController', ['$scope', '$rootScope', function($scope, $rootScope) {
$rootScope.$on('Changed', function(event, data){
$scope.isEmailing = data;
})
$scope.successOnClick = function(){
$scope.$emit('Changed', !$scope.isEmailing);
}
}]);
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="MyController">
<h3 ng-style="{'background-color' : isEmailing ? 'red' : 'white'}">First controller</h3>
<input type='button' ng-click='successOnClick()' value='Change color'/>
</div>
<div ng-controller="MyController">
<h3 ng-style="{'background-color' : isEmailing ? 'red' : 'white'}">Second controller</h3>
<input type='button' ng-click='successOnClick()' value='Change color'/>
</div>
</div>
If one controller located inside another you can try to use $scope.$parent.isEmailing(where .$parent can be typed several times, depending on nesting level), but it is very uncomfortable. If your controllers located at different routes, you should pass data from one controler to another via route parameters or custom AngularJS service or $rootScope.

How to repopulate user entered form values in angular JS when the REST API call fails

I am having an angular js form with dropdowns and text boxes ,on submitting the form I am planning to call an REST API to save the user entered values. i Would like to know if in case the insert fails, how to re populate the user entered form values in the frontend with an error message
Here is one way you could go about making a copy and re-setting the user deets on. Hope it helps. Here's a Codepen for the below code.
function exampleFactory($http) {
//placeholder exampleFactory
console.log('exampleFactory');
function login() {
return {
data: console.log('data saved')
};
}
return {
login: login
};
}
function exampleController($scope, exampleFactory, $timeout) {
var copyOfUserDeets;
$scope.userForm = {};
$scope.submit = function(userDeets) {
copyOfUserDeets = angular.copy(userDeets);
$scope.userForm = {};
// exampleFactory
// .login(userDeets)
// .then(function(resp) {
// $scope.userForm = {};
// })
// .catch(function(error) {
// $scope.userForm = copyOfUserDeets;
// });
$timeout(function() {
$scope.userForm = copyOfUserDeets;
}, 10000);
};
}
angular
.module('app', [])
.controller('exampleController', exampleController)
.factory('exampleFactory', exampleFactory);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<div class="container-fluid text-center" ng-app="app">
<div class="container text-center" ng-controller="exampleController">
<form name="userLoginForm" ng-submit="submit(userForm)" ng-model="userForm" novalidate>
<input type="email" name="email" ng-model="userForm.email" required="">
<input type="text" name="password" ng-model="userForm.text" required="">
<input type="submit" value="Submit" ng-disabled="userLoginForm.$invalid">
</form>
<pre>{{userForm}}</pre>
</div>
</div>

Directive-validator doesn't catch empty field but filled field

I have the following AngularJS code. It should check if input field is empty when I press Submit button. Submit button broadcasts custom event that directive successfully catches. But it doesn't work when field is empty. It reaches ctrl.$parsers.unshift when I start typing and my field becomes theForm.name.$invalid===true. It seems to work the opposite way.
define(['angular'], function (angular) {
"use strict";
var requiredValidator = angular.module('RequiredValidator', []);
requiredValidator.directive('validateRequired', function () {
var KEY_ERROR = "required";
return {
scope: {
validateRequired: '=validateRequired'
},
require: 'ngModel',
link: function (scope, elem, attr, ctrl) {
function validate(value) {
var valid = !value || value === '' || value === null;
ctrl.$setValidity(KEY_ERROR, valid);
return value;
}
scope.$on('validateEvent', function (event, data) {
if (scope.validateRequired.$submitted) {
console.log("Reachable block when submitted");
ctrl.$parsers.unshift(function (value) {
console.log("Unreachable when input is empty");
return validate(value);
});
ctrl.$formatters.unshift(function (value) {
return validate(value);
});
}
});
}
};
});
return requiredValidator;
});
Form field snippet:
<div>
<input type="text" name="name"
data-ng-class="{ error : theForm.name.$invalid}"
data-ng-model="customer.name"
data-validate-required="theForm">
<span data-ng-show="theForm.name.$invalid" class="error">{{getInputErrorMessage(theForm.name.$error)}}</span>
</div>
You actually don't need such a complex directive for your szenario. You could also handle the logic within a controller like so:
var app = angular.module('form-example', ['ngMessages']);
app.controller('FormCtrl', function($scope) {
var vm = this;
vm.submit = function(form) {
if (form.$invalid) {
angular.forEach(form.$error.required, function(item) {
item.$dirty = true;
});
form.$submitted = false;
} else {
alert('Form submitted!');
}
};
});
label,
button {
display: block;
}
input {
margin: 5px 0;
}
button {
margin-top: 10px;
}
form {
margin: 10px;
}
div[ng-message] {
margin-bottom: 10px;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular-messages.js"></script>
<form ng-app="form-example" name="myForm" ng-controller="FormCtrl as vm" novalidate="" ng-submit="vm.submit(myForm)">
<label for="username">Username</label>
<input id="username" type="text" name="username" ng-model="vm.username" required="" />
<div ng-messages="myForm.username.$error" ng-if="myForm.username.$dirty" role="alert">
<div ng-message="required">Username is required</div>
</div>
<label for="email">E-Mail</label>
<input id="email" type="email" name="email" ng-model="vm.email" required="" />
<div ng-messages="myForm.email.$error" ng-if="myForm.email.$dirty" role="alert">
<div ng-message="required">E-Mail is required</div>
<div ng-message="email">Your E-Mail is not valid</div>
</div>
<button type="submit">Send</button>
</form>
This requires to use at least AngularJS version 1.3.0 since I use the $submitted property of the internal FormController. For more information check the documentation on the FormController. I also use ngMessages which was also introduced in 1.3. This is pretty helpful if you want to display messages in forms in respect to errors.

Reset Validity of ngModel

Recently, I had a problem with Angular form validity. I easy can to add the entry to Array with help ngModel.$setValidity, but I can't to remove it after. My html tag has a lot of valid/invalid classes. I'd tried to do the form to pristine. But it does't work. How that things to do generally? Help me please! (Sorry for my english =) if I've made a mistake somewhere.)
It's not terribly well documented, but you can actually pass in null to the $setValidity() function in order to completely clear a validation flag.
If you want to set it to be valid then simply pass in true
//Reset validity for this control
this.form.firstName.$setValidity('someValidator', null);
//Or set to valid
this.form.firstName.$setValidity('someValidator', true);
And here is a running snippet to demonstrate this technique.
(function() {
'use strict';
function MainCtrl() {
this.firstName = 'Josh';
}
MainCtrl.prototype = {
setInvalid: function(ctrl) {
ctrl.$setValidity('customValidator', false);
},
setPristine: function(ctrl) {
ctrl.$setValidity('customValidator', null);
},
};
angular.module('sample', [])
.controller('MainCtrl', MainCtrl);
}());
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" />
<div class="container" ng-app="sample" ng-controller="MainCtrl as ctrl">
<div class="row">
<div class="col-sm-12">
<form name="ctrl.form">
<div class="form-group" ng-class="{'has-error':ctrl.form.firstName.$invalid}">
<label class="control-label">First Name</label>
<input type="text" class="form-control" name="firstName" ng-model="ctrl.firstName" />
</div>
<button type="button" class="btn btn-danger" ng-click="ctrl.setInvalid(ctrl.form.firstName)">Set Invalid</button>
<button type="button" class="btn btn-success" ng-click="ctrl.setPristine(ctrl.form.firstName)">Set Valid</button>
</form>
</div>
</div>
</div>
(function () {
angular.module("App")
.directive("password", password);
function password() {
var lastTrueRegex = {};
var regexes = {
week: /(?=^.{8,}$).*$/,
pettyWeek: /(?=^.{8,}$)(?=.*\d).*$/,
normal: /(?=^.{8,}$)(?=.*\d)(?=.*[a-z]).*$/,
prettyStrong: /(?=^.{8,}$)(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$/,
strong: /(?=^.{8,}$)(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?![.\n]).*$/,
veryStrong: /(?=^.{8,}$)(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?![.\n])(?=.*[!##$%^&*]+).*$/
};
function forEach(data, callback) {
for (var key in data) {
if (data.hasOwnProperty(key)) {
callback(key, data[key]);
}
}
}
return {
require: "ngModel",
restrict: 'EA',
link: function (scope, element, attributes, ngModel) {
ngModel.$parsers.unshift(function (textValue) {
forEach(regexes, function (key, regex) {
if (regex.test(textValue)){
lastTrueRegex.name = key;
lastTrueRegex.value = true;
}else{
ngModel.$setValidity(key, null);
}
});
if (lastTrueRegex.name){
ngModel.$setValidity(lastTrueRegex.name, lastTrueRegex.value);
return textValue;
}
});
ngModel.$formatters.unshift(function (modelValue) {
//ngModel.$setValidity('strongPass', isValid(modelValue));
return modelValue;
});
}
};
}
})();
<form name="myForm">
<input type="text" name="password" ng-model="textValue" password/>
</form>

Resources