How to build your own service

What is a service?

In AngularJS, a service is a function, or an object, that is available for, and limited to, your application. AngularJS has about 30 built-in services. If you are updating the URL in your application, it is likely that you have already used the $location service.

Differences between a service and a directive?

A service is mainly a way to communicate between controllers. A service does not contain any HTML components. Whereas a directive is used to build widgets, it can contain a view (HTML file) and a controller (JS file).

Why build your own service?

  • Avoid duplicating the same code on multiple pages.
  • Reduce the maintenance into one file.
  • Create a reusable function for all your future projects.
  • Build a function that you can share with the Canvas community.

Building a service is very easy, just follow these steps and you will be able to build your first service in 5 minutes.

Structure of a service

A service is a JS file the following structure:

app.service('serviceName', ['$tm1Ui', '$location', function($tm1Ui, $location) {
    //Do something
    }
}]);

A service can use other services. To enable other services, you will need to add these services as arguments of your service. In the example above the new service called serviceName will be able to use the $tm1Ui and $location service.

How to build your first service?

Building a service is very easy, you just need to copy the code from your controller into a new file. First let's create this new file. Canvas is going to load all files from the JS folder so you can put it anywhere inside the JS folder. In this example we put it inside js/controllers folder.

For example, let's say in our controller we use the function to update the settings. Instead of using the same code in every controllers, we can copy this function:

$scope.updateSettings = function (parameter, options) {
    //Get user settings value from Settings cube
}

And paste it into a new file called globals.js and replace $scope. with this.:

app.service('globals', ['$tm1Ui', '$location', function($tm1Ui, $location) {
    this.updateSettings = function (values, defaults, selections, parameter, options) {
    //Get user settings value from Settings cube
        });
    }
}]);

When this function was in our controller, we were using $scope to get the values of the variables defaults and selections. To be able to use the defaults and selections variables inside our service, we need to pass them as argument of the function in the service.

You can download the all code here:

How to call your service from a controller?

To be able to use a service in a controller, you need first to declare it at the top of the controller:

Then you just need to prefix the function with the service name. In the example below, the function initializeVariables is going to call the function updateSettings from the service globals:

$scope.initializeVariables = function(){
        $tm1Ui.applicationUser("dev").then(function(data){
            $scope.values.user = data;
            globals.updateSettings($scope.values, $scope.defaults, $scope.selections, "Year", {"tm1Dimension":"Year", "tm1Alias":"Financial Year"});
            globals.updateSettings($scope.values, $scope.defaults, $scope.selections, "Version", {"tm1Dimension":"Version", "tm1Alias":"Description"});
        });   
    }

How to call your service from a view?

From the view (HTML page), you can access only functions which are defined in the controller. To call a function from a service, you will have to create a link between the controller and the service using:

$scope.globals = globals; 

By doing so all functions defined in the globals service are now available from the view by using globals.functionName. In our example we trigger the function globals.updateSettings from the SUBNM when the value change using tm1-change:

<tm1-ui-subnm 
  tm1-instance="dev" 
  tm1-dimension="Version" 
  tm1-subset="Default" 
  tm1-default-element="{{defaults.Version}}"
  ng-model="selections.Version" 
  tm1-change='globals.updateSettings(values, defaults, selections, "Version", {"tm1Dimension":"Version", "tm1Alias":"Description", "value":data})'>     </tm1-ui-subnm>

You can download the example here (it includes the view, the controller and the service):