<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="utf-8">
<title>ngAttr</title>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.js"></script>
<script src="ngAttr.js"></script>
</head>
<body ng-controller="AppCtrl">
<script>
var app = angular.module('myApp', []);
app.directive('ngAttr', ngAttrDirective);
app.controller('AppCtrl', function($scope) {
$scope.alert = function() {
alert('Click!');
};
});
</script>
<p>
Classic ng-click (works):
<button ng-click="alert()">Call alert()</button>
</p>
<p>
Now ng-click generated by ng-attr (does not work):
<button ng-attr="{'ng-click=alert()': true}">Call alert()</button>
</p>
</body>
</html>
'use strict';
/**
* See feat(ngAttr): implement conditional/interpolated attributes directive #4269 https://github.com/angular/angular.js/pull/4269
* See feat(ngAttr): implement conditional/interpolated attributes directive https://github.com/caitp/angular.js/commit/4b79321fbd59b4fd7e97ff82257958993185ab01
*/
function attrDirective(name, selector) {
name = 'ngAttr' + name;
return function() {
var ATTR_MATCH = /\s*([^=]+)(=\s*(\S+))?/;
return {
restrict: 'A',
link: function(scope, element, attr) {
var oldVal;
scope.$watch(attr[name], function(value) {
ngAttrWatchAction(scope.$eval(attr[name]));
}, true);
attr.$observe(name, function() {
ngAttrWatchAction(scope.$eval(attr[name]));
});
function ngAttrWatchAction(newVal) {
if (selector === true || scope.$index % 2 === selector) {
if (oldVal && !angular.equals(newVal,oldVal)) {
attrWorker(oldVal, removeAttr);
}
attrWorker(newVal, setAttr);
}
oldVal = angular.copy(newVal);
}
function splitAttr(value) {
var m = ATTR_MATCH.exec(value);
return m && [m[1].replace(/\s+$/, ''), m[3]];
}
function setAttr(value) {
if (value) {
if (value[0] === 'undefined' || value[0] === 'null') {
return;
}
element.attr(value[0], angular.isDefined(value[1]) ? value[1] : '');
}
}
function removeAttr(value) {
if (value) {
element.removeAttr(value[0]);
}
}
function attrWorker(attrVal, action, compare) {
if (angular.isString(attrVal)) {
attrVal = attrVal.split(/\s+/);
}
if (angular.isArray(attrVal)) {
angular.forEach(attrVal, function(v) {
v = splitAttr(v);
action(v);
});
} else if (angular.isObject(attrVal)) {
var attrs = [];
angular.forEach(attrVal, function(v, k) {
k = splitAttr(k);
if (v) {
action(k);
}
});
}
}
}
};
};
}
var ngAttrDirective = attrDirective('', true);