Is it possible to access a service directly from an expression in a template, such as inside an ngClick? I didn't think it was possible, but Angular material's Menu demo seems to inject a custom service $mdOpenMenu as easily as injecting $event into the expression: https://material.angularjs.org/latest/demo/menu
As you can see in the source for the menu controller, the menu directive causes $mdOpenMenu to be assigned to the scope of the markup within that directive, so $mdOpenMenu is available within the markup and can be passed to functions. It isn't a service in the traditional Angular sense. It is just a function that the directive's controller added to the scope.
Related
I've had no success creating an Attribute directive that uses vm in the child elements and uses the directive controller scope and no it's parent scope.
See: http://fiddle.jshell.net/vzuf9psq/
How can I make the second message show the message from the directive controller?
Use directive scope to transfer properties from one controller to another
Use bindToController to bind directive scope to controller (or much better, use Angular component's syntax).
Do not paste template inside directive tag (or use transclude for this purpose)
See Final fiddle
I have two scenarios:
A function defined in a controller is called from a directive (see plunk).
The directive includes a '&' scope restriction to relate the controller and directive functions. If you click on the text, the element click event is triggered in the directive and the controller function is called. $scope.$apply() is used to notify AngularJS of the click event and refresh the value of var on the screen.
A function defined in a directive is called from a controller (see plunk).
The directive doesn't have any scope restriction, meaning that $scope in the controller and scope in the directive are shared. I defined func1() in the directive that can be called from the controller (try clicking on the text), however it seems intrusive as the controller needs to know the name of the function.
Is there a way to define func1() in such a way that the function name is declared in the directive div, similar to scenario 1?
Both options are possible and acceptable depending on how you are building the component.
Option 1 - Controllers should register listeners/callbacks and set attributes on directives (when using isolated scope - which i recommend). Controllers should not call a directives function but instead should change an attribute that has been bound on the directive. The directive if setup correctly should be watching this attribute and update accordingly.
Directives should not know who their controllers are in my opinion, it promotes decoupled code. Instead, controllers should be setting callback functions that directives can invoke at the appropriate time (i.e. letting the controller know something was clicked, selected, deleted, swiped, etc...)
Option 2 - Is acceptable to me when you are building a web component that provides the structure and behavioral logic but does not define the actual individual components UI (not including a possible skeleton UI). For example a list directive. The individual list may not be defined in the directive but "plugged in" for each context or use, giving us a more modular and reusable component. It does require us to know some things about the directive. It also requires that we modify the transclusion function to use the directives scope on the transcluded content instead of the original controllers scope. For an example you can checkout a list component I made as an example to this point.
http://github.com/Spidy88/ng-web-components
A snippet of text from this html page. The sf-list directive is an isolated scope directive that defines a lists behavior. However we can still define what each individual list item looks like with modified transclusion. It relies on us to call selectItem though in order to trigger selection behavior on the list.
<sf-list items="ctrl.emails" listener="ctrl.adapter">
<div class="list-item email" ng-click="selectItem(item)" ng-repeat="item in items track by item.id">
<div class="from">{{ item.from }}:</div>
<div class="subject">{{ item.subject }}</div>
</div>
</sf-list>
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...
<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.
In my controller I am using a service based on $http which on success is updating the $scope.
Also, I want to have the access to the service in my directive, the on ng-click in directive make some POST, and then refresh the data from server and update the scope afterwards. So the route for the signal would be: directive -> service -> controller -> $scope. How can I do that without invoking a method on controller, but invoking it from directive?
I know I can bind some methods between directive and controller, but I have like 8 possible methods and I don't want to write 8 times method1:"&" and <myDirective method1="method1()" method2="method2() "etc... That would be a mess.
I don't want you to write much code for me, just some hints, please...
If you do not create isolated scope, or set scope=true inside your directive, the directive runs within the scope of controller.
So your options then are to either
Have the methods on the controller and access them as normal scope methods in the directive.
Inject the service into directive as you do it in controller and call the service and update the controller scope however you want
Still if you want to make directive reusable, it is better to use isolated scopes.