I am trying to create a directive that will add an ngModel attribute to a tag based on the attribute value. For example:
angular.module('myModule').
directive('myDirective', function() {
return {
link: function(scope, elem, attrs) {
var modelName = 'myPrefix.' + attrs.name;
attrs.$set('ngModel', modelName);
}
};
});
So that this html:
<input name="foo" my-directive></input>
is compiled into
<input name="foo" ng-model="myPrefix.foo" my-directive></input>
It takes the name of the input, attaches a prefix, and sets the ngModel attribute to that value.
When I try to do this in the link function, it seems like the input
isn't being registered with the formController, so that form.foo
returns undefined.
Is it possible to accomplish what I'm trying to do?
EDIT:
It seems like the ngModel
attribute is being set on the HTML, but it is not being registered with the form, or the ngModelController is not being instantiated. If I look at the value of ngModel
in the scope, it does not change when I modify the input.
You should check out the docs for the NgModelController
. It will answer your question. For further explanation, here's the gist:
You can capture a fourth argument to the link:
function, which is your ng-model
value. You use that object to read and set the model.
link: function(scope, element, attrs, ngModel) {
if(!ngModel) return; // do nothing if no ng-model
// Specify how UI should be updated
ngModel.$render = function() {
element.html(ngModel.$viewValue || '');
};
// Listen for change events to enable binding
element.on('blur keyup change', function() {
scope.$apply(read);
});
read(); // initialize
// Write data to the model
function read() {
var html = element.html();
// When we clear the content editable the browser leaves a <br> behind
// If strip-br attribute is provided then we strip this out
if( attrs.stripBr && html == '<br>' ) {
html = '';
}
ngModel.$setViewValue(html);
}
}
Hope that helps.
I was able to accomplish the goal by using a template function. I think it doesn't work in the link function because it occurs after all of the directives have been collected, so the compiler doesn't recognize that an ngModel
directive has been added. I'm not sure why it doesn't work in the compile function, though (even if I set the priority to 100).
Here's the working version of the directive:
angular.module('myModule').
directive('myDirective', function() {
return {
replace: true,
template: function(elem, attr) {
var newElem = '<input ng-model="model.' + attr.name + '">';
return newElem;
}
};
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With