Become a member
to unlock all features

Level Up!

Access all courses & lessons on egghead today and lock-in your price for life.


    Using Services in Angular Directives

    John LindquistJohn Lindquist

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



    Become a Member to view code

    You must be a Member to view code

    Access all courses and lessons, track your progress, gain confidence and expertise.

    Become a Member
    and unlock code for this lesson




    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.