Angular directive for custom validation - angularjs

I'm trying to create the AngularJS directive, which should vilidate the form. The form has two inputs. The valid case is when the imputs are either both empty or both filled with any string value.
<form name="recipientsForm" novalidate>
<md-input-container>
<label>Name</label>
<input name="name" type="text" ng-model="relationship.name">
</md-input-container>
<md-input-container>
<md-select name="type" placeholder="Select your relation... " ng-model="relationship.relationshipType">
<md-option ng-repeat="type in relationshipTypes" value="{{type.relationshipType}}">
{{type.name}}
</md-option>
</md-select>
</md-input-container>
</form>
The divective should be generic for other forms with such kind of validation.
My approach seems not working:
.html:
<form name="recipientsForm" novalidate>
<md-input-container>
<label>Name</label>
<input name="name" type="text" ng-model="relationship.name" value="" empty-or-both-filled="relationship.relationshipType">
<div ng-messages="recipientsForm.name.$error">
<div ng-message="emptyOrBothFilled">Enter name.</div>
</div>
</md-input-container>
<md-input-container>
<md-select name="type" placeholder="Select your relation... " ng-model="relationship.relationshipType" empty-or-both-filled="relationship.name">
<md-option ng-repeat="type in relationshipTypes" value="{{type.relationshipType}}">
{{type.name}}
</md-option>
</md-select>
<div ng-messages="recipientsForm.type.$error">
<div ng-message="emptyOrBothFilled">Pick relationship.</div>
</div>
</md-input-container>
</form>
.js file:
(function () {
'use strict';
angular
.module('app')
.directive('emptyOrBothFilled', [emptyOrBothFilled]);
function emptyOrBothFilled() {
return {
restrict: 'A',
require: 'ngModel',
scope: {
targetNgModel: '=emptyOrBothFilled'
},
link: function($scope, element, attrs, ngModel) {
ngModel.$validators.emptyOrBothFilled = function(val) {
console.log($scope.targetNgModel);
return (!val && !$scope.targetNgModel) || (!!val && !!$scope.targetNgModel);
}
$scope.$watch('targetNgModel', function() {
ngModel.$validate();
})
}
}
}
})();

An alternativ approach just using ng-disabled and ng-required:
<form name="recipientsForm" novalidate>
<md-input-container>
<label>Name</label>
<input name="name" type="text" ng-model="relationship.name">
<div ng-messages="recipientsForm.name.$error">
<div ng-message="emptyOrBothFilled">Enter name.</div>
</div>
</md-input-container>
<md-input-container>
<md-select name="type" placeholder="Select your relation... " ng-model="relationship.relationshipType" ng-disabled="relationship.name" ng-required="relationship.name">
<md-option ng-repeat="type in relationshipTypes" value="{{type.relationshipType}}">
{{type.name}}
</md-option>
</md-select>
</md-input-container>
</form>

Related

Confirm password validation angularjs material design

I want to display an error using angularjs, under the "confirm password" input which should say "Passwords don't match".
<form name="settingsForm" ng-submit="vm.login(vm.credentials)" novalidate>
<md-input-container class="md-block" flex-gt-sm="">
<label translate="MY_PROFILE_NEW_PASSWORD"></label>
<input type="password" name="newPassword" id="password"
ng-model="vm.newPassword"
required=""
ng-minlength="8"
md-maxlength="40">
<div ng-messages="settingsForm.newPassword.$error"
role="alert"
multiple="">
<div ng-message="required"
class="my-message"
translate="LOGIN_PASSWORD_INVALID">
</div>
<div ng-message="minlength"
class="my-message"
translate="MIN_8_CHARS">
</div>
</div>
</md-input-container>
<md-input-container class="md-block" flex-gt-sm="">
<label translate="MY_PROFILE_CONFIRM_NEW_PASSWORD"></label>
<input type="password"
name="confirmPassword"
id="confirmPassword"
ng-model="vm.confirmPassword"
required=""
confirm-password="vm.newPassword"
ng-minlength="8"
md-maxlength="40">
<div ng-messages="settingsForm.$error.confirmPassword"
role="alert" multiple="" >
<div ng-message="required"
class="my-message"
translate="LOGIN_PASSWORD_INVALID">
</div>
<div ng-message="minlength"
class="my-message"
translate="MIN_8_CHARS">
</div>
</div>
<div ng-message="required"
class="my-message"
translate="LOGIN_PASSWORD_INVALID">
</div>
<div ng-message="confirm-password"
class="my-message">
Passwords don't match.
</div>
</md-input-container>
<md-button class="md-raised md-primary btn-auth"
type="submit"
ng-disabled="settingsForm.$invalid"
translate="SUBMIT"
ng-click="vm.changePassword(vm)">
</md-button>
I need to make this form display error messages for each particular case.
I haven't found how "confirm-password" attribute should work for validation.
You have to create a Custom Directive. Try this.
<div data-ng-controller="PasswordController as vmPassword">
<form name="passwordForm">
<md-input-container class="md-block" flex-gt-sm>
<label>Password</label>
<input type="password"
name="password"
ng-model="vmPassword.password"
required
/>
<div ng-messages="passwordForm.password.$error" role="alert" class="form-errors first-name-error">
<div ng-message="required">Password is required.</div>
</div>
</md-input-container>
<md-input-container class="md-block" flex-gt-sm>
<label>Confirm Password</label>
<input type="password"
name="confirm_password"
ng-model="vmPassword.confirm_password"
required
compare-to="vmPassword.password"
/>
<div ng-messages="passwordForm.confirm_password.$error" role="alert" class="form-errors first-name-error">
<div ng-message="required">Password is required.</div>
<div ng-message="compareTo">Passwords do not match</div>
</div>
</md-input-container>
</form>
</div>
Custom Directive
(function () {
"use strict";
angular.module('app').directive('compareTo', compareTo);
compareTo.$inject = [];
function compareTo() {
return {
require: "ngModel",
scope: {
compareTolValue: "=compareTo"
},
link: function(scope, element, attributes, ngModel) {
ngModel.$validators.compareTo = function(modelValue) {
return modelValue == scope.compareTolValue;
};
scope.$watch("compareTolValue", function() {
ngModel.$validate();
});
}
};
}
})();
Goodluck .! :)
Demo here - http://embed.plnkr.co/UK4G4Lm5BCNNe5SWoA9r/

Get all the values of form fields having same ng-model in angularjs

I am new in angularjs and making a dynamic form fields with ng-repeat and all my fields having the same ng-model
My Code:
<form name="dataset" class="md-inline-form" novalidate>
<div ng-repeat="column in columns">
<input type="hidden" name="column_name" ng-model="dataset.columnName" value="{{column}}">
<label for="">Column: <strong>{{column}}</strong></label>
<div layout="column" layout-gt-xs="row">
<md-input-container flex>
<label>Select Type</label>
<md-select name="type" ng-model="dataset.type" required>
<md-option value="string">String</md-option>
<md-option value="numeric">Numeric</md-option>
</md-select>
<div class="errors" ng-messages="dataset.state.$error">
<div ng-message="required">Required</div>
</div>
</md-input-container>
</div>
</div>
<md-button type="submit" ng-click="SavevalidateColumns()" class="md-raised md-accent" aria-label="Submit">Validate Now</md-button>
</form>
Now i just want to get the values of my all dynamically created fields in my controller. Can any one help me regarding this ?
You have to use my code.
<form name="dataset" class="md-inline-form" novalidate>
<div ng-repeat="column in columns">
<input type="hidden" name="column_name" ng-model="dataset.columnName" value="{{column}}">
<label for="">Column: <strong>{{column}}</strong></label>
<div layout="column" layout-gt-xs="row">
<md-input-container flex>
<label>Select Type</label>
<md-select name="type" ng-model="dataset.type" required>
<md-option value="string">String</md-option>
<md-option value="numeric">Numeric</md-option>
</md-select>
<div class="errors" ng-messages="dataset.state.$error">
<div ng-message="required">Required</div>
</div>
</md-input-container>
</div>
</div>
<md-button type="submit" ng-click="SavevalidateColumns(dataset)" class="md-raised md-accent" aria-label="Submit">Validate Now</md-button>
</form>
First You have to pass data in funciton.
Your controller code:
(function () {
'use strict';
angular.module('moduleName', [])
.controller('myCtrl',
function ($scope) {
$scope.SavevalidateColumns = function (dataset) {
var colName = dataset.columnName;
var type = dataset.type;
console.log(colName + "::::" + type);
};
});
})();
You have to inject this module into app also.

AngularJS 1.5 - same as above address

I want to implement a 'same as above' mailing address and permanent address. But then i tick on the checkbox, it does not show that the mailing address and permanent address are the same. help?
controller
$scope.candidateData.MailingAddress = {};
$scope.$watch('mailingSameAsPermanent', function (value) {
if (value) {
$scope.candidateData.Address = $scope.candidateData.MailingAddress;
} else {
$scope.candidateData.Address = angular.copy($scope.candidateData.Address);
}
partial HTML:
<h3>Permanent Address</h3>
<md-input-container class="md-block">
<label>Address</label>
<input name="add" ng-model="candidateData.Address.Address1">
<div ng-messages="CandidateDetails.add.$error">
<div ng-message="required">
Please enter your address
</div>
</div>
</md-input-container>
<md-input-container md-no-float class="md-block">
<input ng-model="candidateData.Address.Address2" placeholder="Address 2">
</md-input-container>
<div layout-gt-sm="row">
<md-input-container class="md-block" flex-gt-sm>
<label>Country</label>
<md-select ng-model="candidateData.Address.Country">
<md-option> <!--ng-repeat="country in countries" value="{{country.Country}}"-->>
{{candidateData.Address.Country}}
</md-option>
</md-select>
</md-input-container>
<md-input-container class="md-block" flex-gt-sm>
<label>Zip Code</label>
<input name="postalCode" ng-model="candidateData.Address.Zip" placeholder="12345"
required ng-pattern="/^[0-9]{5}$/">
<div ng-messages="CandidateDetails.postalCode.$error" role="alert" multiple>
<div ng-message="required" class="my-message">You must supply a zip code.</div>
<div ng-message="pattern" class="my-message">
That doesn't look like a valid postal
code.
</div>
</div>
</div>
<h3>Mailing Address</h3>
<md-checkbox ng-model="mailingSameAsPermanent" >
Tick if your mailing address is the same as your permanent address
</md-checkbox>
<div>
<md-input-container class="md-block">
<label>Address</label>
<input name="add" ng-model="candidateData.MailingAddress.Address1" ng-disabled="mailingSameAsPermanent">
<div ng-messages="CandidateDetails.add.$error">
<div ng-message="required">
Please enter your address
</div>
</div>
</md-input-container>
<md-input-container md-no-float class="md-block">
<input ng-model="candidateData.MailingAddress.Address2" placeholder="Address 2" ng-disabled="mailingSameAsPermanent">
</md-input-container>
<div layout-gt-sm="row">
<md-input-container class="md-block" flex-gt-sm>
<label>Country</label>
<md-select ng-model="candidateData.Address.Country">
<md-option>
<!--ng-repeat="country in countries" value="{{country.Country}}"-->>
{{candidateData.Address.Country}}
</md-option>
</md-select>
</md-input-container>
<md-input-container class="md-block" flex-gt-sm>
<label>Zip Code</label>
<input name="postalCode" ng-model="candidateData.Address.Zip" placeholder="12345"
required ng-pattern="/^[0-9]{5}$/">
<div ng-messages="CandidateDetails.postalCode.$error" role="alert" multiple>
<div ng-message="required" class="my-message">You must supply a zip code.</div>
<div ng-message="pattern" class="my-message">
That doesn't look like a valid postal
code.
</div>
</div>
</div>
</div>
I've implemented the functionality the way you want to achieve but in different approach.
You can check out below link to understand.
https://jsfiddle.net/alpeshprajapati/U3pVM/23941/
$scope.permanent = {address:'helloworld', state: 'gujarat'};
$scope.click = function(){
if($scope.sameasabove){
$scope.mail = angular.copy($scope.permanent);
} else {
$scope.mail = {};
}
};
You need to implement this in your code.
Try this one
<input type="checkbox" ng-model="sameas" ng-click="!sameas?permanentAddress=presentAddress:permanentAddress={}" />

form.$valid always returning false angularjs

I'm trying to make validations to my form in an ng-repeat which now always returning as false even though all the inputs are filled and correct.
Here's my update function:
$scope.updateChannel = function (channel) {
if (channelForm.$valid) {
Channels.update({
_id: channel._id
}, {
$set: {
name: channel.name,
category: channel.category,
tags: channel.tags,
logo: channel.logo
}
}, function (error, data) {
if (error) {
console.log('unable to update the channel: ' + error);
} else {
console.log('Done! ' + data);
}
});
} else {
console.log('fix errors');
}
}
and here's my form:
<form ng-show="channel.edit == true" name="channelForm" ng-submit="updateChannel(channel)" novalidate>
<md-input-container>
<label for="name">Nombre</label>
<input type="text" name="name" ng-model="channel.name" md-maxlength="20" required>
<div ng-messages="channelForm.name.$error;">
<div ng-message="required">Esto es requerido.</div>
<div ng-message="md-maxlength">Demaciados carácteres.</div>
</div>
</md-input-container>
<md-input-container class="md-block">
<label for="category">Categorias</label>
<md-select name="category" ng-model="channel.category" multiple required>
<md-option ng-repeat="kit in kits" value="{{kit.name}}">{{kit.name}}</md-option>
</md-select>
<div class="errors" ng-messages="channelForm.category.$error">
<div ng-message="required">Esto es requerido.</div>
</div>
</md-input-container>
<md-input-container>
<label for="number">Canal</label>
<input type="number" name="number" ng-model="channel.number" ng-model-options="{ updateOn: 'blur' }" maxlength="5" required>
<div ng-messages="channelForm.number.$error;">
<div ng-message="required">Esto es requerido.</div>
<div ng-message="md-maxlength">Demaciados carácteres.</div>
</div>
</md-input-container>
<md-input-container>
<label for="tags">Tags(separar con espacio)</label>
<input type="text" name="tags" ng-model="channel.tags" md-maxlength="20" required>
<div ng-messages="channelForm.tags.$error;">
<div ng-message="required">Esto es requerido.</div>
<div ng-message="md-maxlength">Demaciados carácteres.</div>
</div>
</md-input-container>
<md-input-container>
<label for="logo">Logo</label>
<input type="text" name="logo" ng-model="channel.logo" required>
<div ng-messages="channelForm.logo.$error;">
<div ng-message="required">Esto es requerido.</div>
</div>
</md-input-container>
<md-button type="submit" class="md-raised md-primary" ng-click="channel.edit = false" ng-disabled="channelForm.$invalid">Guardar</md-button>
<md-button class="md-raised" ng-click="channel.edit = false">Cancelar</md-button>
<md-button class="md-raised md-warn" ng-click="removeChannel(channel)">Borrar</md-button>
</form>
now this is in an ng-repeat="channel in channels" so I'm not sure if that's the problem.
Also, all the ng-messages seem to be working correctly and even when none of them are showing I'm still unable to update the document.
What am I doing wrong here?
Thanks!
If this is in a ng-repeat, you will end up with a bunch of forms named channelForm
You could put a new controller on the form tag and move updateChannel in that controller.

Why using directive I loose the Material effects?

I'm trying to understand what exactly is happening.
I had a form with Angular Material, something like:
<div layout-gt-sm="row">
<md-input-container class="md-block" flex-gt-sm>
<label>First name</label>
<input ng-model="user.firstName">
</md-input-container>
<md-input-container class="md-block" flex-gt-sm>
<label>Last Name</label>
<input ng-model="theMax">
</md-input-container>
</div>
... with the onfocus and onblur effecs + inputs layout full.
After that working, I change the form to work with directives and the form start to be like:
<div layout-gt-sm="row" class="core no-padding-bottom">
<!-- effect working -->
<md-input-container class="md-block" flex-gt-sm>
<md-icon><i class="material-icons">email</i></md-icon>
<input type="text" name="asd" placeholder="asd">
</md-input-container>
<!-- effect not working -->
<input-test name="name"></input-test>
</div>
... directive template:
<md-input-container class="md-icon-float md-block" flex-gt-sm md-no-float>
<md-icon class="material-icons">
<i class="material-icons">{{ attrs.icon }}</i>
</md-icon>
<input
type="text"
name="{{ attrs.name }}">
<div ng-messages="form[attrs.name].$error" role="alert">
<div ng-message="server">{{ form[attrs.name].$error.serverMessage }}</div>
</div>
</md-input-container>
... the directive:
app.directive('inputTest', function($injector, $q, $location) {
return {
replace: true,
restrict: 'AE',
scope: {
model: '=',
form: '='
},
templateUrl: baseViewPath('directives/form/text.html'),
link: function($scope, $element, $attrs) {
$scope.attrs = $attrs;
$scope.mask = function() {
if(typeof $attrs.mask !== 'undefined') {
return $attrs.mask;
}
};
}
};
});
Now, the form is working 50%, where is been send and validate as well but there's no Material effects and no full fields on screen.
What could that be?
UPDATE
I think that I "fixed" changing the placeholder to label
<label>{{ attrs.placeholder }}</label>

Resources