I want to do something like that, Can it be possible in angularjs
ng-change=\"myDirective = [test]\"
i.e. I simply want to call my directive on ng-change , is it possible in angularjs to call custom directive inside directive.
yes it is possible but for doing this you need another directive for watching changes on your myDirective variable...
when you change value of myDirective middleware directive catches changes and rebuild dom.
I created such a directive for another problem but it can be used in your situation so I edit this PLUNKER for you...
Related
Suppose I am customizing an angularjs bootstrap carousel and making it as a directive. I want to customize the current function that the ng-click calls on each left/right arrow so it calls a custom function before the original function defined in the bootstrap. I know calling multiple functions in ng-click can be done by
ng-click = "customFunction();originalFunctionFromBootstrap()"
But, in angular carousel, the left and right arrow is defined inside its bootstrap template and I don't want to modify the template using $templatecache.
Is there a way to add new ng-click in my controller without having to modify the template cache?
EDIT:
The current workaround that I can have is using
document.querySelector('.left.carousel-control').addEventListener('click', function(){...})
And of course this is not angular way of doing this. Plus, if I use ng-click from ng-touch, this will not be called as well. Is there a way on how to modify the ng-click?
If you inherit the scope of the directive you can save the library function in a variable and override the function with your logic. Then call the function that you saved on a variable so everything keep working.
var _superClickMethod = scope.originalFunctionFromBootstrap;
scope.originalFunctionFromBootstrap = function () {
// custom logic
_superClickMethod();
}
Other solution is to wrap the carrusel bootstrap plugin in a directive of yours. I recommend the last option.
What I ended up doing is:
document.querySelector('.left.carousel-control').setAttribute('ng-click', 'customFunction()');
$compile(document.querySelector('.left.carousel-control'))(scope);
And this solves my problem.
I 'm trying to write a collapsible, reusable calculator directive, that binds to an input field (in the parent scope). This input field itself has a ngModel binding.
When the user presses the equals-button of my directive this parent scope model should be updated. I need to isolate the scope so I can reuse it:
Here is the simplified code and how I would like to use it:
http://plnkr.co/edit/OSOcxydJWh8K520nstAU?p=preview
I tried passing in the values as an attribute. but that does not work because I don't know how to update this attribute inside of the controller(I tried the $attrs service).
So how can I update the model from the directive?
Maybe you're overthinking it, maybe I'm underthinking it. Either way, here's all I did to change yours to make it work:
if ($scope.operator ==='+') {
$scope.field = parseInt($scope.field) + $scope.operand;
}
I uncommented your scope and then I made sure that your controller made reference to the data you had exposed in your scope. That's it.
And here's a working version of your Plunker: http://plnkr.co/edit/btBi3E
You need to use ngModelController. Here's a link with docs, with a handy example:
NgModelController
<my-dir ng-show="isVisible()"></my-dir>
isVisible will call isVisible in the controller.
What if I want it to call isVisible inside the my-dir directive instead?
Note: my-dir in my application is a tree control that recursively calls itself using $compile so there may be many of them nested inside each other. Using a singleton service may not work because of asynchronicity.
EDIT: in retrospect I the correct answer was to create a filter for my directive. What can I say, Angular is a different way of doing things.
If you're using a directive you have full control of the element. Just do this: <my-dir check-visible="true"></my-dir>
Then in the directive's link function you can just go: if(attrs.checkVisible) isVisible();
Then you can show or hide the element however you like.
I have a controller that has an object on its scope: $scope.objToTrack.
I have a directive that is inside a nested view that $watches for changes to that object.
It has isolate scope, but objToTrack is set as = so that it can be watched.
When I click the directive, it calls an expression that is a method on the controller which changes objToTrack.
Here's a plunker to illustrate my setup.
The problem is that objToTrack $watch callback isn't fired, although the object is changed.
If you switch between Test1 and Test2 states, changes made to objToTrack are visible. It's just that I don't understand why it doesn't work right away on click.
Thanks.
To answer question...if you bind your own event handlers to an element, and change angular scope within that event handler you need to call $apply so angular is made aware of the change and can run a digest
Example You have:
element.on('click',function(){
scope.onClick({number:RNG.int(200,300)});
});
Would need to be changed to:
element.on('click',function(){
scope.$apply(function(){
scope.onClick({number:RNG.int(200,300)});
});
});
It is a lot simpler if you use event directives already provided by angular. In this case you are writing considerable amount of extra code vs using ng-click. It also makes testing a lot easier when you stay within angular as much as possible
Also, if you want to pass an object into your directive you should not use curly braces.
In html, use obj-to-track="objToTrack", instead of obj-to-track="{{objToTrack}}".
Like this:
<div simple-directive obj-to-track="objToTrack" class="directive"></div>
And in directive.js: use '=' for bi-directional binding of the objToTrack.
Like this:
scope:{
objToTrack:'='
}
In your "test*.html" files, replace "on-click" by "ng-click".
"on-click" doesn't look in your current controller, "ng-click" does.
I have a directive and I want to change the ng-model value given with this directive...
I'm setting scope: {ngModel: '='} and I'm changing the ngModel value (on click event) inside my directive but I can't see changes on my external/original object.
This plunker shows the problem...
There are a few things wrong here, all of them common mistakes.
Event handlers registered through jQuery using $(...).on(...) will be executed outside of angular context, so angular will not know when things have updated. To address this, you must wrap the contents in a scope.$apply call like so
$('#aaa').on('click', function() {
_scope.$apply(function(){
_scope.ngModel = 'Other Value';
updateTemplate();
});
});
This will update the binding to the input with ng-model. In fact you can avoid having to do this by using the ng-click directive.
With angular, you do not need to update templates like this yourself using .html(...). Binding is one of the major features of the framework. Instead of having the update function, you can use interpolation by putting an expression inside of {{ ... }} and your DOM will be updated when your model is. For example when defining the directive you can use
template: '<div id="aaa">{{ngModel}}</div>'
to set your template and {{ngModel}} will show the current value of ngModel.
ngModel is not just any attribute, it is a powerful directive. If you need your own directive to be able to declare the current model valid or invalid, or to interact with forms then you should use this through the require property on your controller (see here).
If you don't need those features then you should be calling your attribute something different to avoid conflict.
I have updated the plunker to include these points.