Angular Material 0.9.7 Form Validation Example - angularjs

I want to validate form using angularjs and angular-material built-in directives including messages under field like, input, select, radio buttons.
There are some specific requirements:
The Form fields should have equal heights
The radio buttons i.e. md-radio should be inline
The location of messages under fields should be similar
The angular-material select i.e. md-select should be width = 100%

I did some tweaks to Salal Aslam answer:
submit button is enable
erorr messages aren't shown on untouched form
validate on submit
validate on touching element
Example on JSFiddle and below.
HTML:
<form name="myForm" ng-app="myApp" ng-controller="myController" class="container-fluid" ng-submit="myForm.$valid && submit()" novalidate>
<div class="row">
<div class="col-xs-8">
<md-input-container md-is-error="myForm.name.$invalid && (myForm.$submitted || myForm.name.$dirty)">
<label>Name</label>
<input name="name" id="name" ng-model="obj.name" ng-required="true">
<div ng-messages="myForm.name.$error" ng-if="myForm.$submitted || myForm.name.$touched">
<div ng-message="required">Campaign Name is required.</div>
</div>
</md-input-container>
</div>
<div class="col-xs-8">
<md-input-container md-is-error="myForm.myselect.$invalid && (myForm.$submitted || myForm.myselect.$dirty)">
<md-select name="myselect" id="myselect" placeholder="myselect" ng-model="obj.myselect" ng-required="true">
<md-option ng-repeat="o in options" ng-value="o">{{o}}</md-option>
</md-select>
<div ng-messages="myForm.myselect.$error" ng-if="myForm.$submitted || myForm.myselect.$touched">
<div ng-message="required">myselect is required.</div>
</div>
</md-input-container>
</div>
<div class="col-xs-8">
<md-input-container md-is-error="myForm.status.$invalid && (myForm.$submitted || myForm.status.$dirty)">
<md-radio-group name="status" id="status" ng-model="obj.status" ng-required="true" class="">
<md-radio-button ng-repeat="s in statuses" ng-value="s">{{s}}</md-radio-button>
</md-radio-group>
<div ng-messages="myForm.status.$error" ng-if="myForm.$submitted || myForm.status.$touched">
<div ng-message="required">status is required.</div>
</div>
</md-input-container>
</div>
</div>
<md-button type="button" ng-click="reset()">RESET</md-button>
<md-button type="submit" class="md-primary">SUBMIT</md-button>
</form>
JS:
var app = angular
.module('myApp', ['ngAnimate', 'ngAria', 'ngMaterial', 'ngMessages'])
.controller('myController', function ($scope) {
$scope.statuses = ['Planned', 'Confirmed', 'Cancelled'];
$scope.options = ['Option 1', 'Option 2', 'Option 3', 'Option 4', '...'];
$scope.submit = function() {
// submit code goes here
};
$scope.reset = function() {
$scope.obj = {
name: "",
myselect: "",
status: ""
}
};
$scope.reset();
});

I created this fiddle for the requirements mentioned. I am posting this here to help someone new to angularjs or angular-material
<form name="myForm" ng-app="myApp" ng-controller="myController" class="container-fluid" ng-submit="submit()">
<div class="row">
<div class="col-xs-8">
<md-input-container>
<label>Name</label>
<input name="name" id="name" ng-model="obj.name" ng-required="true">
<div ng-messages="myForm.name.$error">
<div ng-message="required">Campaign Name is required.</div>
</div>
</md-input-container>
</div>
<div class="col-xs-8">
<md-input-container>
<md-select name="myselect" id="myselect" placeholder="myselect" ng-model="obj.myselect" ng-required="true">
<md-option ng-repeat="o in options" ng-value="o">{{o}}</md-option>
</md-select>
<div ng-messages="myForm.myselect.$error">
<div ng-message="required">myselect is required.</div>
</div>
</md-input-container>
</div>
<div class="col-xs-8">
<md-input-container>
<md-radio-group name="status" id="status" ng-model="obj.status" ng-required="true" class="">
<md-radio-button ng-repeat="s in statuses" ng-value="s">{{s}}</md-radio-button>
</md-radio-group>
<div ng-messages="myForm.status.$error">
<div ng-message="required">myselect is required.</div>
</div>
</md-input-container>
</div>
</div>
<md-button type="button" ng-click="reset()">RESET</md-button>
<md-button class="md-primary" ng-disabled="myForm.$invalid">SUBMIT</md-button>
</form>
var app = angular
.module('myApp', ['ngAnimate', 'ngAria', 'ngMaterial', 'ngMessages'])
.controller('myController', function ($scope) {
$scope.statuses = ['Planned', 'Confirmed', 'Cancelled'];
$scope.options = ['Option 1', 'Option 2', 'Option 3', 'Option 4', '...'];
$scope.submit = function() {
// submit code goes here
};
$scope.reset = function() {
$scope.obj = {
name: "",
myselect: "",
status: ""
}
}
$scope.reset();
});
md-input-container > md-select {
margin-top: 0;
padding-bottom: 0; }
md-input-container > md-select > md-select-label {
width: 100%; }
md-input-container > md-radio-group {
padding: 24px 2px 0; }
md-input-container > md-radio-group > md-radio-button {
margin: 8px 5px 0;
display: inline-block; }
fiddle link
Update 1: Created this pen for angular 1.4.2 and angular-material v0.10.0

Related

Disabling Button in Master Page using AngularJS

I have the following Master Page:
<body ng-app="app" ng-controller="controller" ng-cloak>
<div class="header" ng-bind="header"></div>
<div class="content">
<!-- This content will switch -->
<ui-view></ui-view>
</div>
<div class="footer" ng-show="showFooter">
<md-button class="md-raised md-primary" ng-click="cancel()">Cancel</md-button>
<md-button class="md-raised md-primary" ng-click="ok()">OK</md-button>
</div>
And the following Add Contact page which goes in <ui-view> tags:
<form name="form">
<button class="round-button"></button><br />
<md-input-container>
<input name="name" ng-model="name" placeholder="Name" minlength="3">
<div ng-messages="form.name.$error" ng-show="form.name.$dirty">
<div ng-message="required">This is required.</div>
<div ng-message="minlength">Name has to be at least 3 characters long.</div>
</div>
</md-input-container>
<br />
<md-input-container>
<label>Phone</label>
<input name="phone" ng-model="phone" placeholder="Phone" ng-pattern="/^[0]{1}[5]{1}[0-9]{1}[0-9]{7}$/">
<div ng-messages="form.phone.$error" ng-show="form.phone.$dirty">
<div ng-message="required">This is required.</div>
<div ng-message="pattern">Please enter a valid phone number.</div>
</div>
</md-input-container>
<br />
<md-input-container>
<label>Mail</label>
<input name="mail" ng-model="mail" placeholder="Mail" ng-pattern="/^[\w\-\.\+]+\#[a-zA-Z0-9\.\-]+\.[a-zA-z0-9]{2,4}$/">
<div ng-messages="form.mail.$error" ng-show="form.mail.$dirty">
<div ng-message="pattern">Please enter a valid mail.</div>
</div>
</md-input-container>
<br />
</form>
My Controller for Add Contact page is as follows:
controller: function ($scope, $state, $rootScope,$http) {
$rootScope.cancel = function () {
$state.go("contacts");
};
$rootScope.ok = function () {
var contactInfo = {
name: $scope.name,
phone: $scope.phone,
mail: $scope.mail,
address: $scope.address
};
$http.post("/api/Contact", contactInfo)
.then(function (res) {
alert("contact added successfully");
});
$state.go("contacts");
};
$rootScope.header = "Add Contact";
$rootScope.showFooter = true;
Before I call the web service using $http , I would like the OK button in the Master Page to be disabled until all fields in the form have been filled correctly.
Is there a way to achieve this goal?
You should be able to accomplish this by putting a ng-disabled directive on the button and have it check if the form is valid.
<md-button class="md-raised md-primary" ng-disabled="!form.$valid" ng-click="ok()">OK</md-button>

md dialog not working properly?

I'm new to angular material:
I want to show dialog for editing records in a table:
I referenced angular material and angular aria, used ngMaterial dependency and $mdDialog service.
I have a div containing all editing fields, the div visibility is set to hidden:
<div style="visibility: hidden">
<div class="md-dialog-container" id="taskEdit">
<md-dialog style="width:100%; height:100%" layout-padding>
<md-toolbar>
<div class="md-toolbar-tools">
<h2>Edit Task</h2>
<span flex></span>
</div>
</md-toolbar>
<ng-form name="TaskForm">
<div layout-gt-sm="row">
<md-input-container>
<label>Task Title</label>
<input name="TaskTitle" ng-model="task.title" required>
<div ng-messages="TaskForm.TaskTitle.$error">
<div ng-message="required">This is required</div>
</div>
</md-input-container>
<md-input-container class="md-block" flex-gt-sm>
<label>Description</label>
<textarea ng-model="task.description" md-maxlength="150" md-select-on-focus></textarea>
</md-input-container>
<md-input-container class="md-block">
<label>Due Date</label>
<md-datepicker style="margin-top: 2px;" ng-model="task.dueDate"></md-datepicker>
</md-input-container>
<md-input-container>
<label>Task Status</label>
<input name="TaskStatus" ng-model="task.status">
</md-input-container>
</div>
</ng-form>
<input class="btn btn-primary" style="width:15%" type="submit" ng-disabled="!TaskForm.$valid" ng-click="EditTask()" value="Submit" aria-label="submit" />
</md-dialog>
</div>
</div>
here's the showDialog function::
$scope.showDialog = function () {
$mdDialog.show({
controller: DialogController,
contentElement: '#taskEdit',
parent: angular.element(document.body),
clickOutsideToClose: true
});
};
function DialogController($scope, $mdDialog) {
$scope.hide = function () {
$mdDialog.hide();
};
$scope.cancel = function () {
$mdDialog.cancel();
};
}
but when I click the button, the dialog is not appearing properly, it lacks the animation and is rendered in the same layer as the parent page:
You need to refer the angular material css
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.0.4/angular-material.css">

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.

why scope variable is not accessible in angular components

I have written a angular directive to read the file input data. However the updated scope variable is not accessible when I click on update button. why I am unable to access the file variable that is updated in ngFileSelect directive?
JS
// Define the `changeWord` module
angular.module('changeWord', []);
/// <reference path="changeWord.component.js" />
angular.
module('changeWord').
component('changeWord', {
templateUrl: 'change-word/change-word.template.html',
controller: function ChangeWordController($scope, dictionaryService) {
var self = this;
//$rootScope.loggedIn = $cookies.get('loggedIn');
self.formShowing = false;
$scope.search = function () {
dictionaryService.getWordsStartWith(self.searchText, function (r) {
self.searchResults = r;
});
};
$scope.change = function (id) {
dictionaryService.getWord(id, result => {
self.key = id;
self.word = result.word;
self.wordInEnglish = result.wordInEnglish;
self.pronunciation = result.pronunciation;
var syns ='';
angular.forEach(result.synonyms, a =>{
syns += (syns == '') ? a.wordInEnglish : ', ' + a.wordInEnglish;
})
self.synonyms = syns;
syns = '';
angular.forEach(result.antonyms, a => {
syns += (syns == '') ? a.wordInEnglish : ', ' + a.wordInEnglish;
})
self.antonyms = syns;
});
}
$scope.clear = function () {
angular.element(document.querySelector('#pFile')).val(null);
self.word = '';
self.wordInEnglish = '';
self.pronunciation = '';
self.synonyms = '';
self.antonyms = '';
};
$scope.update = function () {
dictionaryService.deleteWord(self.key);
// unable to access the scope here
dictionaryService.addNewWord(self.word, self.wordInEnglish, self.pronunciation, $scope.file, self.synonyms, self.antonyms);
this.clear();
self.formShowing = false;
}
}
}).directive("ngFileSelect", function () {
return {
link: function ($scope, el) {
el.bind("change", function (e) {
$scope.file = (e.srcElement || e.target).files[0];
//$scope.update();
})
}
}
});
HTML
<div ng-cloak>
<form name="changeForm" button-form ng-submit="update()" ng-if="$ctrl.formShowing">
<md-card flex flex-gt-md="70">
<md-card-header>
<md-card-avatar>
<md-icon class="md-avatar-icon">edit</md-icon>
</md-card-avatar>
<md-card-header-text>
<span class="md-title">Change Existing Word</span>
<span class="md-subhead">in kannada dictionary</span>
</md-card-header-text>
</md-card-header>
<md-card-content>
<md-input-container class="md-block">
<input name="word" ng-model="$ctrl.word" placeholder="Word in Kannada" required />
<div ng-messages="changeForm.word.$error" ng-show="changeForm.word.$dirty" role="alert">
<div ng-message="required">This is required!</div>
</div>
</md-input-container>
<md-input-container class="md-block">
<input name="wordInEnglish" ng-model="$ctrl.wordInEnglish" placeholder="Word in English" disabled />
<div ng-messages="changeForm.wordInEnglish.$error" ng-show="changeForm.wordInEnglish.$dirty" role="alert">
<div ng-message="required">This is required!</div>
</div>
</md-input-container>
<p flex layout="row">
<md-input-container class="md-block" flex="50">
<input ng-model="$ctrl.pronunciation" placeholder="Pronunciation" />
</md-input-container>
<md-input-container class="md-block" flex="50">
<input id="pFile" type="file" ng-File-Select accept="audio/*" capture aria-label="Pronunciation Audio">
</md-input-container>
</p>
<md-input-container class="md-block">
<textarea ng-model="$ctrl.synonyms" placeholder="Synonyms"></textarea>
</md-input-container>
<md-input-container class="md-block">
<textarea ng-model="$ctrl.antonyms" placeholder="Antonyms"></textarea>
</md-input-container>
</md-card-content>
<md-card-actions>
<md-button class="md-raised md-primary" type="submit">Save</md-button>
<md-button class="md-accent" ng-click="$ctrl.formShowing = !$ctrl.formShowing">Cancel</md-button>
</md-card-actions>
</md-card>
</form>
<md-content class="md-padding">
<form name="searchForm" button-form ng-submit="search()">
<md-input-container md-no-float class="md-block">
<input name="searchText" ng-model="$ctrl.searchText" type="text" placeholder="Search">
<md-icon style="display:inline-block;" type="submit">search</md-icon>
<div class="hint" ng-show="searchForm.searchText.$dirty">Press Enter to search</div>
</md-input-container>
</form>
<md-list flex>
<md-list-item class="md-2-line" ng-repeat="result in $ctrl.searchResults" ng-click="null">
<div class="md-list-item-text" layout="column">
<h3>{{ result.wordInEnglish }}</h3>
<p>{{ result.word }}</p>
<md-button name="ch" class="md-raised md-primary md-secondary" ng-click="$ctrl.formShowing=!$ctrl.formShowing; change(result.$id);">Change</md-button>
</div>
</md-list-item>
</md-list>
</md-content>
</div>
Perfect, $scope is not existing in component. Need to use keyword this

How to get back data from DB after sent it from client side?

I have profile page in angular js, after I filled and sent them to DB. Then once again if I come back to the same profile page I didn't get any values in the field.
profile.html
<form name="profileForm">
<br/>
<div flex style="max-width:700px;">
<md-input-container class="md-block">
<label>Name</label>
<input ng-model="vm.name"></input>
</md-input-container>
</div>
<div flex style="max-width:700px;">
<md-input-container class="md-block">
<label>Mobile Number</label>
<input ng-model="vm.mobile"></input>
</md-input-container>
</div>
<div flex style="max-width:700px;">
<md-input-container class="md-block">
<label>Email</label>
<input ng-model="vm.email"></input>
</md-input-container>
</div>
<div flex style="max-width:700px;">
<label>DOB:</label>
<md-datepicker ng-model="vm.profileForm.dob" md-placeholder="Enter date">
</md-datepicker>
</div>
<div flex style="max-width:700px;">
<md-input-container class="md-block" >
<label>Country</label>
<md-select ng-model="vm.profileForm.Country" ng-change="vm.getCountryStates()">
<md-option ng-repeat="countryName in vm.countries" value="{{countryName.id}}" >
{{countryName.country}}
</md-option>
</md-select>
</md-input-container>
</div>
<div flex style="max-width:700px;">
<md-input-container class="md-block" >
<label>State</label>
<md-select ng-model="vm.profileForm.State" ng-change = "vm.getStateCities()">
<md-option ng-repeat="stateName in vm.states" value="{{stateName.Id}}">
{{stateName.state}}
</md-option>
</md-select>
</md-input-container>
</div>
<div flex style="max-width:700px;">
<md-input-container class="md-block" >
<label>City</label>
<md-select ng-model="vm.profileForm.City">
<md-option ng-repeat="cityName in vm.cities" value="{{cityName.Id}}">
{{cityName.city}}
</md-option>
</md-select>
</md-input-container>
</div>
<div flex style="max-width:700px;">
<md-input-container class="md-block" >
<label>Postal Code</label>
<input name="postalCode" ng-model="vm.profileForm.postalCode" ng-pattern="/^[0-9]{6}$/" md-maxlength="6">
</md-input-container>
</div>
<span style="color:green; font-size:20px;">{{vm.message}}</span>
<div layout="row" layout-align="space-between center">
<div>
<img src="assets/icons/fonts/backArrow.png" alt="image caption" style="width:18px; height:18px">
<a ng-href ng-click="vm.nextTab()" >Back</a>
</div>
<div style="margin-right:300px">
<a ng-href="http://localhost:3000/pages/dashboard">Skip</a>
<md-button class="md-raised md-primary" ng-click="vm.profileInfo(vm.profileForm);">Save & Continue</md-button>
</div>
</div>
</form>
In the picture first 3 values getting through ngStorage, after filled remaining fields data stored in DB. For chekcBox I have used cascading dropdown.
profile.js
(function ()
{
'use strict';
angular
.module('app.invite-friends')
.controller('InviteFriendsController', InviteFriendsController);
/** #ngInject */
function InviteFriendsController(Friendslist, $localStorage, $scope, $http, $location, CustomerService)
{
var vm = this;
vm.countries = CustomerService.getCountry();
vm.getCountryStates = function(){
vm.states = CustomerService.getCountryState(vm.profileForm.Country);
vm.cities =[];
}
vm.getStateCities = function(){
vm.cities = CustomerService.getStateCity(vm.profileForm.State);
}
vm.uid = $localStorage._id;
vm.profileInfo = function(userData){
$http({
url:'http://192.168.2.8:7200/api/profile_save',
method:'POST',
data: {info:userData, loginId:vm.uid}
}).then(function(res){
if(res.data.success){
vm.message = 'Your profile information has been saved successfully.';
$location.path('/pages/dashboard')
}
}, function(error){
alert(error.data);
});
};
$http({
url:'http://192.168.2.8:7200/api/checkIfExists',
method:'POST',
data: {userId: vm.uid}
}).success(function(res){
vm.name = res.result[0].name;
vm.mobile = res.result[0].mobile;
vm.email = res.result[0].email;
vm.DOB = res.result[0].DOB;
vm.Country = res.result[0].Country;
vm.State = res.result[0].State;
vm.City = res.result[0].City;
vm.postalCode = res.result[0].PostCode;
}, function(error){
alert(error.data);
});
}
})();
All you ng-model is getting or updating data to vm.profileForm in the view where as while you setting data to view form controller you are adding properties to vm, not to vm.profileForm
Change the following code in $http success
from
vm.DOB = res.result[0].DOB;
vm.Country = res.result[0].Country;
vm.State = res.result[0].State;
vm.City = res.result[0].City;
vm.postalCode = res.result[0].PostCode;
to
vm.profileForm.dob = res.result[0].DOB;
vm.profileForm.Country = res.result[0].Country;
vm.profileForm.State = res.result[0].State;
vm.profileForm.City = res.result[0].City;
vm.profileForm.postalCode = res.result[0].PostCode;

Resources