I'm building an application based on AngularJs and GMaps API v3. The issue I've came up with is that I need a way to call methods of the directive's controller from another directives (that's easy with require) and from the same directive.
Let's put it in an example:
I've got a directive that renders the map using GMaps JS lib. and also render some markers and also I've got another directive that handles navigation (i.e. Changing routes). When I go from route A to route B I need to erase the markers and leave the map blank.
So which is the best way to achive this? Should I build three directives? One with all the render methods and destroy markers methods and then call them from the other directives? Or is there a way to inject the directive's controller into the same directive?
So I've googled a bit an I've found this!
https://github.com/bennadel/AngularJS-Directive-Controllers/blob/master/app/directives/master.js#L11
Just like you said #musically_ut the controller is executed before the link function so it's could be injected into the link func. and make it's method available.
The controller for a directive executes before the link function and all $scope declarations made in the controller are available on the scope of the same directive.
Hence, the controller is injected into the directive itself.
Demo: http://plnkr.co/edit/HnwJ0w0VTLbNOC87k74n?p=preview
Related
I am using AngularJS 1.5 and using ‘$emit’ to send an event to parent controller to refresh parent controller data. On ‘$On’ I have written the logic to refresh the parent controller data.
Now, Parent controller data is being updated but after that it is unable to bind data for the child controller from where ‘$emit’ was triggered.
I tried to use ‘$apply’ but it is saying that ‘$digest’ is already in progress. I have also use Batrang tool to view the data and it is showing that page having all those data but it is not being displayed on UI.
Can anybody tell me how to force angular to bind those data with HTML Control which is already available on the page.
I cannot put sample code here because it's a live project & I'll have to create a sample project to replicate the issue. Even though If it is not easy to answer my query without sample code then I will put sample code on Plunker in a day.
Based on Angular documentation, there are two methods to declare controller in HTML:
one binds methods and properties directly onto the controller using ng-controller="SettingsController1 as settings"
one injects $scope into the controller: ng-controller="SettingsController2"
The second option is more common in the Angular community, and is
generally used in boilerplates and in this guide. However, there are
advantages to binding properties directly to the controller and
avoiding scope.
Using controller as makes it obvious which controller you are
accessing in the template when multiple controllers apply to an
element. If you are writing your controllers as classes you have
easier access to the properties and methods, which will appear on the
scope, from inside the controller code. Since there is always a . in
the bindings, you don't have to worry about prototypal inheritance
masking primitives.
So you could always refer to parent scope in child scope by using controller as:
<div ng-controller="parentController as parent">
<span>{{parent.title}}</span>
<div ng-controller="childController as child">
<span>{{parent.title}}</span>
<span>{{child.title}}</span>
</div>
</div>
Suppose my angular js app(myApp) has a controller and directive, How would I be declaring both?
angular.module("myApp",[])
.controller("myController"......
angular.module("myApp")
.directive("myDirective".......
OR
angular.module("myApp",[])
.directive("myDirective".......
angular.module("myApp")
.controller("myController"......
If you see the above code, I am defining my angular app on a controller, and then just retrieving it for the directive. In the second case, I am defining my app for a directive, and retrieving it for a controller.
Which is the right way? How to decide on what is the correct way?
Both are correct. It doesn't affect the way the application is bootstrapped.
You only need to understand what angular.module() does.
angular.module("myApp",[]) creates a new AngularJS module named "myApp" with the dependencies passed as the second parameter.
angular.module("myApp") is a getter. It returns the module if it has been created before.
Both return the same object. So then, you can add your directives and controllers in the order you want.
Once everything is loaded, AngularJS starts the bootstrapping process. See the AngularJS documentation.
I'm making a dynamic web page with angular, the content from the main page should change, but to avoid writing too much code i decided to make it generic, but to know what type of content is being requested i need to send this parameter from a link/button with a ng-click, this would'nt be a problem but when i have to change the controllers i can't read the parameter.
ng-click="name='Name change'"
Here i'm trying to change a $rootScope variable named name, i tried
ng-click="$rootScope.name='Name change'"
even with a service function, but looks like doesn't work (i don't know too much about angularjs so i tried )
ng-click="$service.cambiarTipo='Name change'"
i made a plunker http://plnkr.co/edit/1BN76SbUAHuOSHs02gpL?p=preview
If you check the console log, you will see that the variable it's undefined, obviously if i change $rootScope.name from a controller i can see it from the other controller, but that's not useful since i need that feed from the user not the controller.
How i can change a rootScope variable from html?
Here'a one using a shared service between the two controller without using $rootscope at all. http://plnkr.co/edit/maKNHgVH20GxTJeCEveh
Note that ng-click is calling the service function. I'm assuming the function is for changing the name.
ng-click="service.cambiarTipo('Name change')"
You really shouldn't be using $rootScope all that much, let alone modifying it from the template. With that said, you can assign $rootScope to a $scope variable and access from the template like normal scoped variable. plunker
Controller:
$scope.rs = $rootScope
Template:
rs.name = 'Name Change'
I would like to reiterate that this is not something you should be doing as it goes against the angular way.
I am writing an app in AngularJS. I need to expose a function that will be called by an outside library.
I need to have my third party library call
executeFunction(param)
and have my angular app respond accordingly.
My first thought was to create a directive that I could apply to a page that would tell the page to listen for this event(function) to be called but I can't seem to wrap my head around how to do this.
If by "outside library" you mean pure javascript/jquery, there are a number of answers to this question. They all propose the same solution, namely that the Controller is exposed via the DOM element id, see the following links:
Call Angular Function with Jquery
AngularJS. How to call controller function from outside of controller component
Creating a factory or service will not help as you have no way to inject/expose an angular service to a jquery function.
Rather than the above solutions, I would suggest trying to write an event handler. You could create an angularjs directive with a link function that registers a jquery custom event listener. The directive would contain a nested controller to handler the required logic. Your jquery/javascript code could then simply trigger the event (passing along any data required)
jQuery customer events:
https://learn.jquery.com/events/introduction-to-custom-events/
I think all of this is however, bad practice. I would recommend that you reconsider the design of what you are trying to accomplish.
you can make an factory or service or even more robust solution will be to make ab complete module
angular.modue("myLib")
.factory("myLibFactory",function(){
return{
executeFunction :function(param){}
}
})
I am loading an angular 'template' using ajax. This template renders a bootstrap modal form when I call $compile ... this works, everything fine here. But what I need is support of embedding controllers within this lazy loaded 'template' (Preferably I want to handle this client side so on server side everything can just look normal).
The thing is when I use ng-controller inside this template and define a function controller inside a script tag it fails. It tells me it cant find the controller function. I understand why this is happening, the script has not yet been initialized. I am just looking for a solution. How can I make the embedded script tags initialize first? Should I extract them, inject them somewhere and then compile the remainder? Or is there a more elegant way?
Lets have look in AngularJS documentation and show the integration with the browser event loop.
So you can see that AngularJS have its own event loop, which consists of three phases: compile, digest and apply.
When you call compile it will only loads the html markup and insert it. You should call apply also.
With apply you will set the execution scope. This will register an watcher that listens to changes.