- Refactor an Angular app from
controller as
method to$scope
method - Describe what services are in Angular
- Be familiar with the 3 types of services we will see
- Explain dependency injection
- Write a Service
From the Angular Services documentation:
Angular services are substitutable objects that are wired together using dependency injection (DI). You can use services to organize and share code across your app.
Angular services are:
- Lazily instantiated – Angular only instantiates a service when an application component depends on it.
- Singletons – Each component dependent on a service gets a reference to the single instance generated by the service factory.
Angular offers several useful services (like
$http
,$scope
, or$log
), but for most applications you'll also want to create your own."
Note: Like other core Angular identifiers, built-in services always start with
$
(e.g.$http
).
- Remembering all of the great things rails taught us about web development like MVC, modularity, and encapsulation, Services can be thought of as the
Model
of our application. Using services allows us to follow one of our favorite rails conventions ofFat Models, Skinny Controllers
, and provides a place for us to place our data logic without bloating our controllers.
- In Angular.js, we will generally see 3 different types of services, but we will favor one specific type
- Angular provides us with three ways to create and register our own service:
- Factory
- Service
- Provider
- When you’re using a Factory you create an object, add properties to it, then return that same object. When you pass this service into your controller, those properties on the object will now be available in that controller through your factory.
app.controller('myFactoryCtrl', function ($scope, myFactory) {
$scope.artist = myFactory.getArtist()
})
app.factory('myFactory', function () {
var _artist = '';
var service = {}
service.getArtist = function () {
return _artist
}
return service;
})
- When you’re using Service, it’s instantiated with the ‘new’ keyword. Because of that, you’ll add properties to ‘this’ and the service will return ‘this’. When you pass the service into your controller, those properties on ‘this’ will now be available on that controller through your service.
app.controller('myServiceCtrl', function ($scope, myService) {
$scope.artist = myService.getArtist();
});
app.service('myService', function () {
var _artist = '';
this.getArtist = function () {
return _artist;
}
});
- These will rarely be used
- Providers are the only service you can pass into your .config() function. Use a provider when you want to provide module-wide configuration for your service object before making it available.
app.controller('myProviderCtrl', function ($scope, myProvider) {
$scope.artist = myProvider.getArtist();
$scope.data.thingFromConfig = myProvider.thingOnConfig;
});
app.provider('myProvider', function () {
this._artist = '';
this.thingFromConfig = '';
//Only the properties on the object returned from $get are available in the controller.
this.$get = function () {
var that = this;
return {
getArtist: function () {
return that._artist;
},
thingonConfig: that.thingFromConfig
}
}
});
app.config(function (myProviderProvider) {
myProviderProvider.thingFromConfig = 'This was set in config()';
})
- We will gradually be getting more and more into the semantics and granularity of services in Angular, but for right now, I wanted to introduce you to the 3 ways we can write them
- The most common way is to use the
Factory
syntax because- it's easier, and has simpler syntax
- and it mirrors the other patterns we have learned about how to write JavaScript
- In
angular.js
like we have seen, we have a couple different ways to do things - Although we have multiple ways to write angular code, we should talk about syntax so we don't trigger errors
- Now, syntax such as this looks fine and you'll probably see a lot of examples like this
angular.module('app')
.controller('AppCtrl', function($scope) {
$scope.sayHi(name) {
console.log("Hi " + name);
}
})
- There are some problems with it
- The biggest problem is it is not
min-safe
. - WHAT IS MIN SAFE???
- min safe means that the code that we write is safe to feed through a program that minifies our code for us
- although there are ways around this, for the time being, the safest way to handle this is to write min safe code which involves writing is like this
- min safe means that the code that we write is safe to feed through a program that minifies our code for us
angular.module('app')
.controller('MyController', MyController);
MyController.$inject = ['ServiceName']
function MyController(ServiceName) {
}
or like this
angular.module('app').controller('MyController', ['$scope', 'serviceName', function($scope, serviceName) {
$scope.sayHi = function() {
console.log("Hi");
}
}])
- using the basics we know, and our handy javascript knowledge, let's put together our first service
- In your workstations, make a new folder (name it whatever you like),
cd
into it, runtouch index.html
and add this html
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8">
<title>Injecting a service</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<script src="injecting_services.js"></script>
</head>
<body>
<div ng-controller="DemoController as demo">
<button ng-click="demo.handleClick()">Click me</button>
</div>
</body>
</html>
- then in that same folder, run
touch injecting_services.js
and paste in this starter
angular.module('app', []);
angular.module('app').controller('DemoController', DemoController);
- The first thing we want to do is to inject a service that angular gives us for free, the
$log
service. - The
$log
services does what you think it does, and it is just a fancierconsole.log
- The first thing we want to do is to inject our service inside our controller. Let's do that like this
DemoController.$inject = ['$log'];
-
What that line above does, is it is telling angular, that we want to inject the
$log
service into ourDemoController
-
This allows us access to all of
$log
benefits -
let's build out the rest of our controller
function DemoController($log) {
var vm = this;
vm.handleClick = function(){
$log.info('i was clicked');
}
}
- this example shows how we use services to manage data and communicate with the rest of our app. But it would be great if it was more interactive....
- In that same work space, touch another file. I'm gonna call mine
example
- then touch another
js
file. Copy and paste this html starter
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8">
<title>Example App</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<script src="another_services.js"></script>
</head>
<body>
<div ng-controller="MyController as ctrl">
<h1>Hello {{ctrl.user}}</h1>
<input type="text" ng-model="ctrl.user">
<button ng-click="ctrl.reverse()">reverse</button>
</div>
</body>
</html>
- now let's add in some more javascript starter
angular.module('app', []);
angular.module('app')
.factory('MyService', MyService)
.controller('MyController', MyController);
- what this code does is it tells angular we are setting it up and calling some dependencies
- now the service we want to make is something that reverses words. so to first accomplish that, let's code the rest
- What is an Angular Service (definition)?
- What is one Angular core or built-in service besides
$scope
? - How do we tell our controller which services to use?