I'm working on customize a input directive which including a label. I tried several days and refer to some articles.
The only problem is that except ng-change, ng-blur and ng-focus, all the other event work. https://jsfiddle.net/luneyq/mw3oz2pr/
Of course I can bind these three event manually myself and they can work as https://jsfiddle.net/luneyq/bp7f3z1o/
But I really don't know why ng-change, ng-blur and ng-focus don't work. Is there any special on these three event? Anyone can help on this?
My codes are as below:
<div ng-app="myApp">
<div ng-controller="MainController">
<my-input type="number" name="valueNumber1" ng-model="obj.valueNumber1" label="Age" ng-click="log('click')" ng-change="log('change')" ng-blur="log('blur')" ng-focus="log('focus')" ng-mouseleave="log('mouseleave')"></my-input>
<div id="result"></div>
</div>
The JS:
var app = angular.module("myApp", []);
app.controller('MainController', function($scope, $window){
$scope.obj = {valueNumber1: 10};
$scope.log = function(text) {
document.getElementById("result").innerHTML = text + ':' + $scope.obj.valueNumber1 + "<br>" + document.getElementById("result").innerHTML;
};
});
app.directive('myInput', function() {
return {
require: '^ngModel',
restrict: 'EA',
scope: {
ngModel: '=',
name: '@name',
label: '@label'
},
replace: true,
transclude: true,
priority: 10,
template: '<div>' +
'<label for="{{ name }}">{{label}}</label>' +
'<input id="{{ name }}" ng-model="ngModel" />' +
'</div>',
compile: function(tElement, tAttrs, transclude) {
var tInput = tElement.find('input');
// Move the attributed given to 'custom-input' to the real input field
angular.forEach(tAttrs, function(value, key) {
if (key.charAt(0) == '$')
return;
tInput.attr(key, value);
});
tElement.replaceWith('<div class="cbay-input-div">' + tElement.html() + '</div>');
return;
}
};
});
Thanks in advance.
The issue is that compilation/transclusion/replace don't work the way you think they work (not sure where you made an incorrect assumption).
What is wrong with your code:
1). You are using incorrect attribute name: you should use
tInput.attr(tAttrs.$attr[key], value);
instead oftInput.attr(key, value);
.2). All the directives specified at
my-input
are compiled and linked despite your changes to thetElement
incompile
function. Proof is here - https://jsfiddle.net/fyuz3auc/3/, take a look at themyTest
directive and its output in console: it is still applied to themyInput
despite any of your effort.3). You specified
scope
for your directive. Thus it has an isolated scope, thus anything you've compiled inside it has no access tolog
function ofMainController
, that's why yourlog
s aren't working. Here is the fiddle proving that: https://jsfiddle.net/m5tba2mf/1/ (take a look at$scope.log = $scope.$parent.log
inlink
function returned fromcompile
).In order to solve the second issue I suggest you to try alternative approach - I am using this at my project, and like it very much. The idea is to use
terminal
in conjunction with extremely high priority and$compile
. Here is the updated fiddle, I think it is pretty straightforward what I do there: https://jsfiddle.net/uoat55sj/1/.