I'm trying to create a custom component that uses a dynamic ng-model inside-out the directive.
As an example, I could invoke different components like:
<custom-dir ng-model="domainModel1"></custom-dir>
<custom-dir ng-model="domainModel2"></custom-dir>
With a directive like:
app.directive('customDir', function() {
return {
restrict: 'EA',
require: '^ngModel',
scope: {
ngModel: '=dirValue',
},
template: '<input ng-model="dirValue" />',
link: function(scope, element, attrs, ctrl) {
scope.dirValue = 'New';
}
};
});
The idea is that the textbox from the directive would change if the model changes, and in the other way around.
The thing is that I've tried different approaches with no success at all, you can check one of this here: http://plnkr.co/edit/7MzDJsP8ZJ59nASjz31g?p=preview In this example, I'm expecting to have the value 'New' in both of the inputs, since I'm changing the model from the directive and is a bi-directional bound (=). But somehow is not bound in the right way. :(
I will be really grateful if someone give some light on that. Thanks in advance!
Something like this?
http://jsfiddle.net/bateast/RJmhB/1/
HTML:
<body ng-app="test">
<my-dir ng-model="test"></my-dir>
<input type="text" ng-model="test"/>
</body>
JS:
angular.module('test', [])
.directive('myDir', function() {
return {
restrict: 'E',
scope: {
ngModel: '='
},
template: '<div><input type="text" ng-model="ngModel"></div>',
};
});
Related
Question is simple - why this work like this work?
angular.module('test1', [])
.directive('myDir', function() {
return {
replace:true,
restrict: 'E',
template: '<input type="text">',
};
}).directive('nogo', function() {
return {
replace:true,
restrict: 'E',
template: '<div><input type="text"></div>',
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="test1">
<my-dir ng-model="test"></my-dir>
<nogo ng-model="test"></nogo>
<input type="text" ng-model="test"/>
</body>
The only difference between two directive is that template for second wrapped with 'div'.
But one work, another doesn't.
Really - I don't understand - why working one is on. But it is.
the problem is ng-model does not work on div.
change :
.directive('nogo', function() {
return {
replace:true,
restrict: 'E',
template: '<div><input type="text"></div>',
};
});
to
.directive('nogo', function() {
return {
replace:true,
restrict: 'E',
template: '<div><input ng-model='test' type="text"></div>',
};
});
dont forget to remove ng-model from <nogo>*remove ng-model*</nogo>
it is working..
Your problem here is that you are applying the model to the <div>, here is another question with more information about this problem.
And in this particular case you can change the bind into the template in order to make it work.
angular.module('test1', [])
.directive('myDir', function() {
return {
replace:true,
restrict: 'E',
template: '<input type="text">',
};
}).directive('nogo', function() {
return {
replace:true,
restrict: 'E',
template: '<div><input type="text" ng-model="test"></div>',
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="test1">
<my-dir ng-model="test"></my-dir>
<nogo ng-model="test"></nogo>
<input type="text" ng-model="test"/>
</body>
Also on the ng-model docs says:
The ngModel directive binds an input,select, textarea (or custom form control)
I was going to use Plunker to assist me in testing a directive, but first I just wanted to create one to test plunker was working, so I put in some sample code. Guess what, basic directives are not working and I have no idea why.
My directives:
app.directive('attributeDirective', function() {
return {
restrict: 'A',
link: function(scope, iElement, iAttrs) {
iElement.bind('click', function() {
console.log('clicked attributeDirective');
});
iElement.bind('mouseover', function() {
iElement.css('cursor', 'pointer');
});
}
};
});
app.directive('elementDirective', function() {
return {
restrict: 'E',
replace: true,
template: '<h2>this is elementDirective</h2>',
link: function(scope, iElement, iAttrs) {
iElement.bind('click', function() {
console.log('clicked elementDirective');
});
iElement.bind('mouseover', function() {
iElement.css('cursor', 'pointer');
});
}
};
});
My html:
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<h2 attributeDirective>Here is my attribute directive</h2>
<elementDirective></elementDirective>
</body>
http://plnkr.co/edit/H9vPhV
while calling a directive in html you should replacecamelcase in directives name like this,
<element-directive></element-directive> and not as it is,
<elementDirective></elementDirective>
like you did.
Hope this helps!!!
PLUNKER
see through the custom directives here
You should use
<h2 attribute-directive>Here is my attribute directive</h2>
See http://plnkr.co/edit/2aGGDRw6SdYNc1joSVI1?p=preview
Common problem - you can't use camel case in your HTML element declaration.
Try <element-directive></element-directive>
Use restrict: 'A' in your directive to refer to attribute.
Use restrict: 'E' in your directive to refer to element.
Find the plunkr: "http://plnkr.co/edit/b1cf6l?p=preview"
Also call your directive using:
<h2 attribute-directive>Here is my attribute directive</h2>
<element-directive></element-directive>
In the following AngularJS code, when you type stuff into the input field, I was expecting the div below the input to update with what is typed in, but it doesn't. Any reason why?:
html
<div ng-app="myApp">
<input type="text" ng-model="city" placeholder="Enter a city" />
<div ng-sparkline ng-model="city" ></div>
</div>
javascript
var app = angular.module('myApp', []);
app.directive('ngSparkline', function () {
return {
restrict: 'A',
require: '^ngModel',
template: '<div class="sparkline"><h4>Weather for {{ngModel}}</h4></div>'
}
});
http://jsfiddle.net/AndroidDev/vT6tQ/12/
Add ngModel to the scope as mentioned below -
app.directive('ngSparkline', function () {
return {
restrict: 'A',
require: '^ngModel',
scope: {
ngModel: '='
},
template: '<div class="sparkline"><h4>Weather for {{ngModel}}</h4></div>'
}
});
Updated Fiddle
It should be
template: '<div class="sparkline"><h4>Weather for {{city}}</h4></div>'
since you are binding the model to city
JSFiddle
The basic issue with this code is you aren't sharing "ngModel" with the directive (which creates a new scope). That said, this could be easier to read by using the attributes and link function. Making these changes I ended up with:
HTML
<div ng-sparkline="city" ></div>
Javascript
app.directive('ngSparkline', function ($compile) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var newElement = '<div class="sparkline"><h4>Weather for {{' + attrs.ngSparkline + '}}</h4></div>';
element.append(angular.element($compile(newElement)(scope)));
}
}
});
Using this pattern you can include any dynamic html or angular code you want in your directive and it will be compiled with the $compile service. That means you don't need to use the scope property - variables are inherited "automatically"!
Hope that helps!
See the fiddle: http://jsfiddle.net/8RVYD/1/
template: '<div class="sparkline"><h4>Weather for {{city}}</h4></div>'
the issue is that require option means that ngSparkline directive expects ngModel directive controller as its link function 4th parameter. your directive can be modified like this:
app.directive('ngSparkline', function () {
return {
restrict: 'A',
require: '^ngModel',
template: '<div class="sparkline"><h4>Weather for {{someModel}}</h4></div>',
link: function(scope, element, attrs, controller) {
controller.$render = function() {
scope.someModel = controller.$viewValue;
}
}
}
});
but this creates someModel variable in scope. that I think isn't necessary for this use case.
fiddle
So, have created a few angular directives -- picture "user controls" around common data entry elements, like a label-textbox pair, etc
The problem we are having is that the zValidate directive does not seem to work from within the directive. Is there something we need to do to make nested directives work?
Edit
Here are the relevant code snippets.
So, first, we have a little directive that adds a label-input pair:
app.directive('afLabelInputPair', function ($compile) {
var directive = {
restrict: 'A',
transclude: true,
replace: true,
scope: { //#textValue =twoWayBinding &oneWayBinding
labelText: '#labelText',
afModel: '=',
afId: '#',
afPlaceholder: '#'
},
templateUrl: './app/templates/af-label-input-pair.html',
link: function (scope, element, attrs) {
scope.opts = attrs;
$compile(element.contents())(scope);
}
}
return directive;
});
Next, we have the template html (this is what's returned from templateUrl:
<div class="form-group">
<label class="control-label" for="{{afId}}">{{labelText}}</label>
<input id="{{afId}}" class="form-control" ng-model="afModel" placeholder="{{afPlaceholder}}" data-z-validate />
</div>
But, we don't get a display of breeze validation errors when we use this directive.
I'm have this code:
<div ng-repeat="param in item.parameters">
<rating param_item="{{param}}"></rating>
</div>
how can i pass the given attribute to the directive template?
Personally, I like creating child scope for element directives:
http://plnkr.co/edit/Dz7fcZaT4KdRDa869rwm?p=preview
app.directive('rating', function() {
return {
restrict: 'E',
scope: {
paramItem: '#'
},
link: function(scope, element, attr){
console.log(scope.paramItem);
}
}
});
There are a couple other ways too, depending on how you expect your directive to work.