Reputation: 40863
I am in the process of creating a few reusable directives for common controls in our application.
For example we have a snip-it of html for amount text boxes
<div class='amount'>
<input type='text' ng-model='dollars'/>
</div>
From there I started to create my directive:
app.directive("amount", function(){
return {
restrict: "E",
template: "<div class='amount'><input type='text'/></div>",
replace: true
}
});
Which renders the following <html/>
<div class="amount ng-pristine ng-valid" ng-model="dollars">
<input type="text">
</div>
Now the ng-model
is on the <div/>
which is not what I want, so I need to create a scope and attach it to the ngModel
and things are happy again.
app.directive("amount", function(){
return {
restrict: "E",
scope:{
ngModel: "="
},
template: "<div class='amount'><input type='text' ng-model='ngModel'/></div>",
replace: true
}
});
Everything works, but lets say I want to also add in a ngChange
directive, does that mean I again need to alter my scope
to include ngChange: "="
? Like so
app.directive("amount", function(){
return {
restrict: "E",
scope:{
ngModel: "=",
ngChange : "="
},
template: "<div class='amount'><input type='text' ng-model='ngModel'/></div>",
replace: true
}
});
Do I need to constantly modify the directives scope to include an infinite possible number of other directives I might require? Or is there a way to copy the directives on the <amount/>
element not to the <div/>
but to the <input/>
E.g.
<amount my-awesome-directive="" ng-disabled="form.$invalid" ng-model="dollarsAndCents" ng-click="aClick()" ng-show="shouldShow()"/>
Turns into
<div class="amount">
<input my-awesome-directive="" type="text" ng-disabled="form.$invalid" ng-click="aClick()" ng-show="shouldShow()" ng-model="dollarsAndCents"/>
</div>
Can something be done during the pre/post compile to copy them over or am I going about this all wrong?
I was able to get something working via simply looping over all attributes and using the $compile()
service. It does work, but is this correct?
app.directive("amount", function ($compile) {
return {
restrict: "E",
template: "<div class='amount'><input type='text' /></div>",
replace: true,
compile: function compile(tElement, tAttrs) {
return function (scope, iElement, iAttrs) {
var attributes = $(iElement).prop("attributes");
var $input = $(iElement).find("input");
$.each(attributes, function () { //loop over all attributes and copy them to the <input/>
if (this.name !== "class") {
$input.attr(this.name, this.value);
}
});
$compile($input)(scope); //compile the input
};
}
};
});
Given the following <html/>
if you add any directive to the <amount/>
it gets copied down to the <input/>
<div ng-app="app">
<amount ng-model="dollars" ng-change="changed = 'I Changed!!!'" ng-click="clicked= 'I Clicked It!'" name="amount"></amount>
<h1>{{dollars}}</h1>
<h2>{{changed}}</h2>
<h3>{{clicked}}</h3>
<input type="button" value="Remove" ng-click="items.splice(items.indexOf(item), 1)"/>
<hr/>
</div>
Upvotes: 9
Views: 7127
Reputation: 18595
Bind a controller and inject $scope
for ease.
.controller('Amount', ['$scope', function($scope) {
$scope.myMoney = '2';
}])
.directive("amount", function(){
restrict: 'EA',
replace: true,
controller: 'Amount',
template: "<div class='amount'><input type='text' ng-model='myMoney'/></div>",
//Cleaner to include as URL if the partial is bigger.
//templateUrl: '/views/amount.html',
link: function(scope, controller) {}
});
Upvotes: -1