Callback on 2 Inputs - angularjs

I have a 2 form input (firstName, lastName) and I want to check if they are unique (form validation) by querying my database. So I basically want to have a callback when two of my input elements is inputted.
What is the angular way of doing this?
I'm thinking of getting the element and using .on('blur') while checking if the other input is valid but this feels very jQuery like.

use ng-blur on the inputs.
Here's an example:
HTML:
<div ng-app='myApp' ng-controller='myCtrl'>
Username : <input type='text' ng-model='model.username' ng-blur='checkInputs()' /><br/>
Password: <input type='text' ng-model='model.password' ng-blur='checkInputs()' /> <br/>
</div>
JS:
var app = angular.module('myApp',[]);
app.controller('myCtrl', function($scope){
$scope.model = {username:'', password:''};
$scope.checkInputs = function(){
if($scope.model.username != '' && $scope.model.password != ''){
if($scope.model.username == 'testuser' || $scope.model.password == 'testpass')
{
alert('insert unique fields!!!!')
}
}
}
});
func will sit in your controller in this case and will have access to the username\password. You need to perform an ajax to check this, but I assume you got the point..
Here's a Fiddle.

Related

Push values to array in controller

I have input fields on the DOM that I'm capturing using ng-model.
In my controller, I have an array:
app.controller('mainCtrl', function() {
// set an empty array
self.manualEntry = [];
/**
* ensure form validation
* #returns boolean - ng-disabled value
*/
self.disableForm = function() {
if (self.manualEntry.length <= 0) {
return true;
}
else {
return false;
}
};
});
In my view, I have input fields:
<form>
<input placeholder="John" ng-model="mainCtrl.manualEntry.firstName"/>
<input placeholder="Smith" ng-model="mainCtrl.manualEntry.lastName"/>
</form>
<button type="submit"
ng-disabled="mainCtrl.disableForm()"
title="Submit">Submit
</button>
I thought that $scope automatically updated the model for use in the controller. I thought using dot notation in the DOM would push these values to the array.
When I update these values, the submit button on the form remains disabled (i.e. disableForm() returns true).
How can I push these values to self.manualEntry when they change or are updated on the DOM?
I am making a large assumption on what you want but it seems regular form validation is the way to go for this. Demo at http://plnkr.co/edit/Nzmk3R8eU0fmbBZRrTBa?p=info.
Controller Code
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
// set an empty array
var self = this;
self.manualEntry = {};
//Let HTML5 handle the form validation itself
self.printInfo = function() {
console.log(self.manualEntry);
};
});
HTML Code:
<body ng-controller="MainCtrl as mainCtrl">
<form ng-submit="mainCtrl.printInfo()">
<input placeholder="John" ng-model="mainCtrl.manualEntry.firstName" ng-required="true" />
<input placeholder="Smith" ng-model="mainCtrl.manualEntry.lastName" ng-required="true" />
<button type="submit" title="Submit">Submit
</button>
</form>
</body>

Resetting form controls after action in Angular

Need a bit of help with this. I am trying to get Angular to reset value of my input box after add control is invoked. This is kind of important when it comes to drop down select boxes. I want to be able to clear what user has selected after the option is pushed to a collection.
I also seems to have an issue with user.fName updating whatever I previously added to the users array but it's probably related to the above.
Also can you see what I am doing wrong with ng-show?
html
<div ng-controller="UserController" name="form">
<div ng-show="form.fName.$touched">Hello {{ user.fName }}</div>
<input type="text" name="fName" ng-model="user.fName">
<a ng-click="addUser(user)">Add</a>
<br>
<div ng-repeat="user in users">{{ user }}</div>
</div>
javascript
function UserController($scope) {
//$scope.user = {
// fName: "Joe",
// lName: "Doe"
//};
$scope.users = [];
$scope.addUser = function (user) {
if($scope.users.indexOf(user) === -1){
$scope.users.push(user);
} else {
// trigger error/notification message
console.log(user, ' already added');
}
user = {}; //clear user
};
}
ngModel will try to bind to the property given by evaluating the expression on the current scope. If the property doesn't already exist on this scope, it will be created implicitly and added to the scope.
You are currently not using the scoped property in your click action but a copy that is passed as a parameter. Change user to $scope.user in your addUser method
Note: your object comparison to identify already added users won't work as you always create new objects that will never match. Change it to some different comparison method like comparing the fName properties.
html
<div ng-controller="UserController" name="form">
<div ng-show="form.fName.$touched">Hello {{ user.fName }}</div>
<input type="text" name="fName" ng-model="user.fName">
<a ng-click="addUser()">Add</a>
<br>
<div ng-repeat="user in users">{{ user }}</div>
</div>
javascript
function UserController($scope) {
$scope.users = [];
$scope.addUser = function () {
if($scope.users.indexOf($scope.user) === -1){
$scope.users.push($scope.user);
} else {
// will never match as indexOf() will always return -1
console.log($scope.user, ' already added');
}
$scope.user = {}; //clear user
};
}
http://plnkr.co/edit/N5FXJdWRl42YrVwJsUuR?p=preview
As for your ng-show question: $touched was introduced in AngularJS 1.3 and you're referencing AngularJS 1.2.x in your Plunker code.

Multiple regular expression pattern on one text area in angular js

I have a text area field where it inputs 4 types of personal details separated by commas. I need to validate each of those 4 values using regular expression. This is my approach but it is not much of the angular way to do the validations.
var form = angular.module('form', []);
form.controller('helloController', ['$scope', function($scope){
var submitted = false;
var validNumber = new RegExp('numberRegExp');
var validArea = new RegExp('areaRegExp');
var validCity = new RegExp('cityRegExp');
$scope.submit = function(hello){
$scope.number = false;
$scope.area = false;
$scope.city = false;
if (issue){
$scope.submitted = true;
var splittedDetails = hello.details.split(",");
var trimmedDetails = $.map(splittedDetails, $.trim);
if (!validNumber.test(trimmedDetails[0])) {
$scope.inputversion.jiraIssue.$invalid = true;
$scope.number = true;
}else if (!validArea.test(trimmedDetails[1])) {
$scope.inputversion.jiraIssue.$invalid = true;
$scope.area = true;
}else if (!validCity.test(trimmedDetails[2])) {
$scope.inputversion.jiraIssue.$invalid = true;
$scope.city = true;
}else{
alert("Form now submitting");
}
}
};
}]);
<form class="form-horizontal" name="helloForm" ng-controller="helloController" ng-submit="submit(hello)" novalidate ng-app="form">
<div class="form-group" ng-class="{ true:'has-error'}[submitted && helloForm.personal-details.$invalid]">
<label for="helloForm" class="col-sm-2 control-label">Details</label>
<div class="col-sm-10">
<textarea class="form-control" rows="5" ng-model="hello.details" placeholder="number, area, city, details ex: 90********, XYX, XYZ" name="personal-details" required></textarea>
<p ng-show="submitted && helloForm.personal-details.$error.required" class="help-block"> Details are required.</p>
<p ng-show="submitted && number" class="help-block">Please check the format of issue number</p>
<p ng-show="submitted && area" class="help-block">Please check the format of product area</p>
<p ng-show="submitted && city" class="help-block">Please check the format of priority</p>
</div>
</div>
</form>
This approach can validate only one detail at a time. But ideally it should validate dynamically in much of the angular way. Please suggest your ideas.
Thanks
No offense, but this seems like a really bad way to validate 3 bits of expected data. Comma delimiting will only work if and only if the user puts 2 and only 2 commas into the field.
Assuming you want persisted data from the form (transfers from one page to another) you will want a Model for this module. The best way to do this is via the .service (since there is only one instance of each named service in a module in Angular). I'll also be using the format that will actually work with minified code and best practices, careof John Papa.
It also assumes you have declared the module elsewhere (declare uses brackets [] while recall does not).
angular.module('form')
.service("DataService", DataService)
DataService.$inject = ["$rootScope"];
function DataService($rootScope) {
var vm = this; //security in declaring (root)scope objects
vm.phone = {value: '', placeholder: 'Enter your phone number'};
vm.area = '';
vm.city = '';
};
Your controller would have little in it aside from the use of the $scope/$rootScope variables (with 2-way binding to fields and the Model) and your submit function for when the user tries to submit.
angular.module('form')
.controller('FormController', FormController);
FormController.$inject = ['$scope', 'DataService'];
function FormController($scope, DataService) {
var vm = this;
vm.phone = DataService.phone;
vm.area = DataService.area;
vm.city= DataService.city;
function submit() {
//persist the data to the next page/controller/etc.
DataService.number = vm.number;
DataService.area = vm.area;
DataService.city = vm.city;
//do work here
};
You can do all of your validation within your HTML, using Angular's 2-way binding of data. Assuming you're also using BootStrap, each field should look similar to the below:
<!-- phone field (required/validated) -->
<div class="row form-group" ng-class="{'has-warning': helloForm.phone.$invalid && helloForm.phone.$dirty,'has-error': helloForm.phone.$error.required && helloForm.phone.$touched}">
<label for="phone" class="col-md-3 control-label">Phone:</label>
<div class="col-md-9">
<input type="text" id="phone" name="phone" ng-model="vm.phone.value" placeholder="{{vm.phone.placeHolder}}" value="{{vm.phone.value}}" ng-required="true"class="skinny form-control" ng-pattern="/^\+?[-0-9)(]{8,31}[0-9x]{0,6}$/i" />
<p class="required" ng-show="helloForm.phone.$invalid || helloForm.phone.$error.required">*</p>
<p class="good" ng-show="helloForm.phone.$valid">✔</p>
</div>
<p class="help-block" ng-show="helloForm.phone.$error.pattern && helloForm.phone.$dirty">Phone format: +15558675309x52 or (555)867-5309x52</p>
<p class="help-block" ng-show="helloForm.phone.$error.required && helloForm.phone.$touched">Phone is a required field</p>
</div><br />
Rather than my E.164 (for international numbers) and American Standard phone combination validation (regex inside the ng-pattern field), you can use curly braces to declare your variable regex comparable. I hope this helps or at least points you in the right direction.
Thanks for reading,
C§

angularjs, dynamic directive form validation

For example, I have a select, and an input (idcard) in the form. The select determines the id-card-type (Tax id, Car license id) of input, I want to add a directive into the input to custom validate its value, and the validation method is different by its type(id-card-type) (determined by the select).
I am thinking to dynamic change the directive to validate, or one directive do validation for all types, but how to pass the type information into the directive.
What should I do?
You could do it without a directive:
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.type = 'tax';
$scope.yourForm = {};
$scope.yourForm.inputType = {};
$scope.yourForm.inputType.$valid = false;
$scope.validate = function(type, text) {
// return boolean based on your validation for the input string and type (tax or car)
$scope.yourForm.inputType.$valid = (type === 'tax');
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<form name="yourForm">
<select ng-model="type" ng-change="validate(type, text)">
<option>tax</option>
<option>car</option>
</select>
<input type="text" name="inputType" ng-model="text">
input valid: {{yourForm.inputType.$valid}}
</form>
</div>
In my example, validation of the input is false when 'car' is selected.
Of course, you can wrap all this into a directive.

Dynamically add input fields with Angular and perform validation on blur

Form at start has 1 input field for address. Bellow there is a link that when clicked adds another input and so on. There is no limitation in number of fields.
Is there more elegant way of adding new elements in model collection in Angular? I'm currently using an array of null elements, and on the link click I just push another null in that array so ng-repeat picks it up. And when I want to submit form I go through that array and filter out elements that are not null.
When input field is focused out/blurred there should be validation performed. I'm currently calling a function from controller on ng-blur event but I'm having trouble passing it current input text value.
Fiddle
HTML:
<div ng-app="TestApp">
<div ng-controller="MainCtrl">
<div ng-repeat="field in fields track by $index">
<input type="text" placeholder="enter the address" ng-model="fields[$index]" ng-blur="validate()" />
</div>
+ Add another input
<br/>
<br/>
List addresses
</div>
</div>
JS:
var app = angular.module("TestApp", []);
app.controller("MainCtrl", function($scope){
$scope.fields = [null];
$scope.addresses = [];
$scope.addField = function(){
$scope.fields.push(null);
};
$scope.listAddresses = function(){
for(var i in $scope.fields){
if($scope.fields[i] !== null){
$scope.addresses[i] = $scope.fields[i];
}
}
alert("Addresses: " + $scope.addresses);
};
$scope.validate = function(){
console.log("Should validate current input");
};
});
Instead of using two arrays, use one and store objects:
$scope.items =
[
{ address: '' }
];
It will now be clearer what the model of the input is, as you don't have to use $index. You can also pass the item to the validate function:
<div ng-repeat="item in items">
<input type="text" ng-model="item.address" ng-blur="validate(item)" placeholder="enter the address" />
</div>
Adding item:
$scope.addItem = function() {
$scope.items.push({ address: '' });
};
Demo: http://plnkr.co/edit/sPlPO2DfrgNHf5AasYlH?p=preview

Resources