17 January 2015

one time binding



<tr ng-repeat="class in ::classes">
	<td></td>
</tr>

ng-repeat syntax means if we add or remove items from classes, it will not affect the underlying classes array on the scope

onetime binding can also be used in directive.

<my-directive name="::variable"></my-driective>

angular.module('text').directive('myDirective', function() {
	return {
		template: '',
        scope: {
			name: '='
		}
	};
})

disabling scope info

when in production enviroment disable debugInfo can improve proformance

angular.module('app').config(function($compileProvider) {
	$compileProvider.debugInfoEnabled(false);
});

this will remove class ng-scope ng-binding on the html markup

restrict DI mode

<html ng-app="app" ng-strict-di>
...
...

when use ng-strict-di mode, every service or controller must be use [] syntax or $inject syntax to inject dependence, otherwise, it will have error

ng-model-options

the model vm.test will be updated as long as the cusor blur

<input type="text" id="xxx" ng-model="vm.test" ng-model-options = "{updateOn:'blur'}"/>

<input type="text" id="xxx" ng-model="vm.test" ng-model-options = "{debounce: 1500}"/>

debounce can be object, which means, it is default to 500, and once it blur, the debounce is 0
<input type="text" id="xxx" ng-model="vm.test" ng-model-options = "{debounce: {'default':500, 'blur':0}}"/>

roll back changes

this only works on the field that as ng-model-options bindings $rollbackViewValue()

vm.cancelEntry = function(control, event) {
	if(event.keyCode === 27) {
		control.$rollbackViewValue();
	}
}

<input type="text" 
	   id="xxx" 
       ng-model="vm.test" 
       ng-model-options = "{updateOn:'blur'}"
	   ng-keyup="vm.cancelEntry(classForm.xxx, $event)"/>

rollback can also proform on from level, this will reset the entire form

<form class="form" name="classForm" ng-submit="vm.submit()" ng-model-options="{updateOn:'submit'}" novalidate>

<button ng-click="classForm.$rollbackViewValue()"> Reset </button>

submission detection

this can be used to detect if form has been submitted

<div ng-if="classForm.$submitted">
	Data was submitted
</div>

binding to a getter/setter function

use the getterSetter model option to bind to a getter/setter function

use at the form level to bind to getter/setter functions for all input elements

ng-model-options=”{ getterSetter: true }”

vm.class.dates = {
	startDate: function(value) {
		if(angular.isDefined(value)) {
			_startDate = value;
   			vm.class.startDate=_startDate;
		}
		return _startDate;
	}

}

<input type="text" 
	   id="xxx" 
       ng-model="vm.class.dates.startDate" 
       ng-model-options = "{ getterSetter: true }"/>


validator


<div class="form-group"
     ng-class="{'has-error':classForm.inputClassName.$invalid && classForm.inputClassName.$dirty}">

</div>

ng-messages  
ng-messages-multiple  // this will display all error messages that matches
ng-message directive

ng-messages-include

<span class="help-block has-error"
	  ng-if="classForm.inputInstructorEmail.$dirty"
	  ng-messages="classForm.inputInstructorEmail.$error"
      ng-messages-include="app/errorMessages.html"
      ng-messages-multiple>
	<span ng-message="minlength">
		overwrite minlength validate message
    </span>
</span>

custom validator


function dateRangeValidator() {
	return {
		restrict: 'A',
        require: 'ngModel',
        scope: {
   			beginDate: '=dateRangeValidator'
        },
    	link: function(scope, element, attrs, ngModel) {
			ngModel.$validators.dateRange = function(modelValue) {
				return Date.parse(modelValue) >= Date.parse(scope.beginDate);
   			};

			scope.$watch('beginDate', function() {
				ngModel.$validate();
			});
		}
	}

} 


<input date-range-validator="vm.class.startDate" .. />

asynchronous validation


$asyncValidator

angular.module('common.directives')
	   .directive('duplicateClassnameValidator', ['$q', 'classResource', duplicateClassNameValidator]);  //classResource is a backend service

function duplicateClassNameValidator($q, classResource) {
	return {
		restrict: 'A',
		require: 'ngModel',
		link: function(scope, element, attrs, ngModel) {
			var classId = attrs.duplicateClassNameValidator;
			ngModel.$asyncValidators.duplicateClassName = function(modelValue) {
				var defer = $q.defer();
				classResource.get({classId: classId, className: modelValue},
					function(response) { defer.reject('exists');},
					function(response) {defer.resolve();});
				return defer.promise();
			}
		}
	};

}

// if the asyncValidator is not fullfilled, the status of the input is $pending, that can be used to show spin
image

<span ng-if="classForm.inputClassName.$pending">
	... Verifying Unique Name
</span>

html5 mode routing

in angular 1.3, to enable html5 model, we must add base tag in the head tag

update router params in controller


$scope.updateRouter = function() {
	$route.updateParams({classIdx: $scope.classIdx});
}

prevent router change


$rootScope.$on('$routeChangeStart', function(event, next, current) {
	if(!!current $$ current.id === 'classes' && current.scope.unsavedChanges) {
		event.preventDefault();
	}
});

$scope.startEditing = function() {
	$scope.unsavedChanges = true;
}
$scope.save = function() {
	$scope.unsavedChanges = false;
}

$scope.$watchGroup

this is very useful for some case you want to watch two fields on the form, and either fields will trigger the listener


$scope.$watchGroup(['propert1', 'propert2'], function(newVals, oldVals) {
	for(var i = 0; i < newVals.length; i++) {
		if(newVals[i] !== oldVals[i]) {
			alert('value changed');
		}
	}
})

$routerProvider.caseInsensitiveMatch = true;

$anchorScroll Service


$location.hash('3'),  this will scroll to the element which id is 3

$anchorScroll.yOffset = 10;
$anchorScorll();  //scroll back to the place that match the url

ES6 Promise


var promise = $q(function(resolve, reject) {
	resolve(...)
})

new filters


   //this will show only 4 charactors of studentId

  // this will show  $99.9

ng-true-value

this is useful for checkbox

when the value of registered is yes or no

<input type="checkbox" ng-true-value="'yes'" ng-false-value="'no'" ng-model="student.registered">

directive controllerAs


...

return {
	scope: ...
	templateUrl: '',
	controllerAs: 'ctrl',
	bindToController: true,     //this will bind the property on of scope to ctrl
	controller: function() {
		this.selected = false;
		this.toggleSelect = function() {
			...
		}
	}
}


$includeContentRequested event


$scope.$on('$includeContentRequested', function(e, nameOfTemplate) {

});
$scope.$on('$includeContentLoaded', function(e, nameOfTemplate) {

});
$scope.$on('$includeContentError', function(e, nameOfTemplate) {

});

<div ng-include="'navBar.html'"></div>

these event will be trigged when ng-include used



blog comments powered by Disqus