I have come across a situation where I need to change the input type of an input box based on the selected value of a dropdown. In other words, if the user selects 'String' from the dropdown then the type of the input should be 'text', etc. I decided to create a directive cuz I'm still learning Angular but also so I don't copy blocks of code all over the place (I need this more than once).
This it the contents of my attempt:
(function () {
"use strict";
angular
.module('app')
.directive('dynamicTypeInput', dynamicTypeInput);
function dynamicTypeInput() {
return {
replace: true,
restrict: 'AE',
require: ['ngModel', '^form'],
scope: {type: '=', placeholder: '@'},
templateUrl: 'app/common/dynamic-type-input/dynamic-type-input.tpl.html',
link : function(scope, element, attrs, ngModel){
//Watch for changes to ngModel, update scope.inputValue
scope.$watch(function(){
return ngModel[0].$modelValue;
}, function (value){
scope.inputValue = value;
});
//Watch inputValue, update the model
scope.$watch('inputValue', function(value){
ngModel[0].$setViewValue(value);
});
//Setup ng-change
if (attrs.ngChange) {
ngModel[0].$viewChangeListeners.push(function () {
scope.$eval(attrs.ngChange);
});
}
}
};
}
})();
Note: The template is simply an ng-switch
that selects the appropriate input box based on the value of scope.type
and the inputs all bind to scope.inputValue
.
I used the answer from this SO question to help me add the ability to add an ng-change attribute and fire correctly. According to that answer I needed to remove the ngModel from the isolated scope, I'm not sure why this is required but, if someone could explain it I'd be grateful.
Removing ngModel from the isolated scope made it more difficult to instantiate directive with an initial value or have the directive update when the model is changed in the main controller so now I watch ngModel[0].$modelValue
and update the local value if it changes.
While the directive works and does what I expect it do but it all seems a bit convoluted and inefficient, is there no way I can achieve what I want in a more simple manner?