Enter Your Email Address to Watch This Lesson

Your link to unlock this lesson will be sent to this email address.

Unlock this lesson and all 959 of the free egghead.io lessons, plus get Angular 1.x content delivered directly to your inbox!



Existing egghead members will not see this. Sign in.

Using Services in Angular Directives

5:19 Angular 1.x lesson by

Directives have dependencies too, and you can use dependency injection to provide services for your directives to use.

Get the Code Now
click to level up

egghead.io comment guidelines

Avatar
egghead.io

Directives have dependencies too, and you can use dependency injection to provide services for your directives to use.

Avatar
Paul

You are using bindToController, which is cool, but I don't think it has any effect in your scenario. appCtrl gets into the template namespace courtesy of controllerAs. I think bindToController lets you do an isolated scope and have those copied onto the controller instance automatically.

In reply to egghead.io
Avatar
Joel

You are using bindToController, which is cool, but I don't think it has any effect in your scenario. appCtrl gets into the template namespace courtesy of controllerAs. I think bindToController lets you do an isolated scope and have those copied onto the controller instance automatically.

This is correct, bindToController isn't needed/used in this circumstance, since we aren't using an isolate scope. It doesn't hurt anything either, but is "cruft"

In reply to Paul
Avatar
John

bindToController is habit now for me (and I just finished recording a bindToController video :) )

I was going to dive more into the concepts/similarities of scope and stateParams, so I was planning on using it, but the video was getting too long so I left it out.

In reply to Paul
Avatar
Paul

I'm glad that you're showing it. I stumbled across it last week. Despite paying attention intently, I missed it. I also am using it full-bore, so kudos for making it part of your regular process. Hopefully it will sink in for people, and look forward to the bindToController video.

OT: Saw your tweet about angular.component and the discussion on the ticket. I keep hoping Angular will use 1.4 to "backport" some of the best practices for 2.0. It would be neat if angular.component was considered a lead-in to the web component concept, if not implementation, for 2.0. But that's the opposite of what you advocated for, which is a low-barrier quick change for syntactic sugar. [wink]

In reply to John
Avatar
Joel

Check out bindToController lesson for some details about that awesome feature.

In reply to Paul
Avatar
John

Yeah, "component" is a loaded word so maybe "widget" makes more sense for what I suggested.

I agree with your idea for 1.X to lead into 2.0 features, but it's still way too early to consider until 2.0 is released. Imagine if 2.0 changed, then 1.X is stuck with the wrong backport concepts :/

In reply to Paul
Avatar
Paul

I didn't see the bindToController video posted, sorry! BTW, you should put date stamps on your pages. Helps me know when a lesson came out (though I can always check the Disqus first post.)

On the 2.0, I think there are things that are here now that will be building blocks in the future. For example, a 1.4 that would be supported when running under Traceur. Perhaps even letting you have an angular.component that pointed at a Traceur class. :) Or, CommonJS support. These are some major "best practices" coming that could, in theory, work now and really change how people think about the future development process.

In reply to John
Avatar
Paul

Back to egghead.io lessons though. [wink] I'm a PyCharm customer. I can NEVER get my Angular setup working as smoothly as your WebStorm setup. I'd love some lessons on Awesome Angular with the JetBrains family.

In reply to John
Avatar
John

WebStorm videos are coming (along with a book shameless self-plug).

And the "bindToController" video was posted right after this one. So you didn't miss it, it just wasn't there yet.

In reply to Paul
Avatar
Martin

Hi John. Is there any particular reason why you left the alertService reference attached to AppController or it can be removed from there, so final result will look like this:

.controller("AppCtrl", function AppCtrl(alertService) {
var app = this;
app.somethingFailed = function () {
alertService.alertMessage = "Invoked from AppCtrl";
alertService.alertType = "success";
};

})
In reply to egghead.io
Avatar
John

This example isn't using it, but if you want to use alertService from the HTML for some other reason in the future then you'll need it.

In reply to Martin

A very common scenario is having a system-wide or application-wide alert message or warning message, where you can put some sort of alertMessage and then set it in your controller, so app.alertMessage = "Something failed."

That way, you can start providing messages and other sorts of things to this component through the controller. Similarly, we could do ng-if and only show it if app.showAlert is true, and set a type which we'll set to app.alertType, so we can go ahead and say app.alertType is "danger" and app.showAlert is true.

We can refresh, you'll see "Something failed," and a nice red alert. It's showing, and we can even add a button to set all these things, so ng-click app.somethingFailed. Say it's "Something Failed," and then wrap this guy in a function and move all this stuff up inside of it. Now this alert will only show up when we click this button.

This is wonderful and all, but what if you wanted to show this alert from another controller or another template or another state? You'd probably extract this all into a service, something like an alertService...

Then you can move all of this stuff, cut this here, put it up in the service, and change this from app to alertService.

Now if we inject the alertService, we can simply expose the alertService on the controller, and then make sure that's also exposed in our application, so here, here, and here, .alertService, and when we refresh this will work just fine because it's being set when the controller is instantiated.

The problem that we run into now is, what if we want to use the alertService for something else and we don't want it to affect this alert component, like we don't want this alert component on this controller page to show up in certain scenarios that we didn't really account for when we set it up? We'd rather just not have the component on this page at all, but we'd like it on other pages.

That problem stems from app being a dependency on this component now. What we can do is actually cut this entire thing out and wrap it with a directive. I'll say directive...and we'll just call this appAlert...and have it return a template of what we just cut out.

We'll update the template in just a second, but the technique I use for injecting services, since we still need the alertService, is from 1.3 there's bindTo controller, which I'll set to true, and the I can say controller AppAlertCtrl as appAlert, and then I'll go ahead and create that controller as well. AppAlertCtrl, AppAlertCtrl, and var appAlert.

Now we simply inject the alert service in here, expose it on appAlert, and then we have access to it in our template, so instead of app we'll say appAlert, and we have a nice self-contained directive that relies on alertService.

To use this, since it's called appAlert, we can say app-alert and when we refresh, you can see that it's working just fine, which means that from other controllers -- inside of somethingFailed I could say app.alertService, alertMessage is "Invoked from appCtrl," add app.alertService.alertType is "success."

Then when we refresh and I click this button, you can see that we now have a "Success" green alert with a new message set from our app controller, meaning that from any controller we could set messages, types, whether or not to show it.

But we also have the flexibility to completely delete this, remove it from our page, and then just drop it into any other page and still have everything we already set up in other controllers work just fine, without having to rely on it living inside a global application controller.

HEY, QUICK QUESTION!
Joel's Head
Why are we asking?