lostsoul29
lostsoul29

Reputation: 756

Example of injecting services in Angular 1.5 components

Can anyone give an example on using services with Angular 1.5 components?

I'm trying to inject a service in an Angular 1.5 component, but it doesn't work.

I have a login component like so:

class Login {
    constructor($scope, $reactive, $state, myService) {
        console.log(myService.somevariable); //doesn't work
    }
}

// create a module
export default angular.module(name, [
    angularMeteor
]).component(name, {
    templateUrl: 'imports/ui/components/${name}/${name}.html',
    controllerAs: name,
    controller: Login
});

My service looks like this:

angular.module(name).service("myService", function () {
    this.somevariable = 'somevalue';
});

I just cant seem to be able to get the service injected in the component.What am I doing wrong?

SOLUTION:

With sebenalern's help, I got it working.

I needed a service to validate an email address using a regular expression. I did it like this:

import angular from 'angular';
import angularMeteor from 'angular-meteor';
class Validator { 
    validateEmail(email) {
        var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
        return re.test(email);
    }
}

const name = 'validator';

// create a module
export default angular.module(name, [
    angularMeteor
])

.service("Validator", Validator);

I then injected the service like so:

import {name as Validator} from '../../../api/services/validator'

class Login {
    constructor($scope, $reactive, $state, Validator) {
        'ngInject';
        this.$state = $state;

        $reactive(this).attach($scope);
        this.Validator = Validator;
    }

    login() {
        if(this.Validator.validateEmail(this.credentials.email)) {
            // email is valid. 
        }
    }    
}

const name = 'login';

export default angular.module(name, [
    angularMeteor,
    Validator
]).component(name, {
    templateUrl: `imports/ui/components/${name}/${name}.html`,
    controllerAs: name,
    controller:Login
})

Hope this helps :)

Upvotes: 5

Views: 11786

Answers (2)

vincentw56
vincentw56

Reputation: 545

Here is how I am doing it and it works well. It works fine with classes. I assume you are using TypeScript.

class AdminHomeService {
    consignment: IConsignment;

    get: () => IConsignment;

    constructor() {
        this.consignment = new Consignment();
        this.consignment.id = 10;
        this.consignment.customer = "Customer3";
        this.consignment.customerList = [{ id: 1, name: "Customer1" }, { id: 2, name: "Customer2" }, { id: 3, name: "Customer3" }];
        this.consignment.shipperList = [{ key: "1", value: "Shipper1" }, { key: "2", value: "Shipper2" }, { key: "3", value: "Shipper3" }];
        this.consignment.consigneeList = [{ key: "1", value: "Consignee1" }, { key: "2", value: "Consignee2" }, { key: "3", value: "Consignee3" }];
        this.consignment.billingList = [{ key: "1", value: "Billing1" }, { key: "2", value: "Billing2" }, { key: "3", value: "Billing3" }];
        this.consignment.carrierList = [{ key: "1", value: "Carrier1" }, { key: "2", value: "Carrier2" }, { key: "3", value: "Carrier3" }];

        this.get = () => {
            return this.consignment;
        }
    }
}

class AdminHomeComponentController {
    consignment: IConsignment;
    selectedCustomer: any;

    static $inject = ["adminHomeService"];

    constructor(private adminHomeService: AdminHomeService) {
        this.consignment = new Consignment();
        this.consignment = this.adminHomeService.get();

        this.selectedCustomer = {};
        this.selectedCustomer.selected = { "name": this.consignment.customer };
    }

    customerAddClick(): void {

    }
}

class AdminHomeComponent implements ng.IComponentOptions {
    bindings: any;
    controller: any;
    templateUrl: string;
    $routeConfig: angular.RouteDefinition[];

    constructor() {
        this.bindings = {
            textBinding: "@",
            dataBinding: "<",
            functionBinding: "&"
        };
        this.controller = AdminHomeComponentController;
        this.templateUrl = "templates/admin.home.html";

        //this.$routeConfig = [
        //    { path: "/admin", name: "AdminHome", component: "adminHome", useAsDefault: true }
        //];
    }
}

angular.module("adminHome", [])
    .component("adminHome", new AdminHomeComponent())
    .service("adminHomeService", AdminHomeService);

This post helped me a lot: http://almerosteyn.com/2016/02/angular15-component-typescript

Upvotes: 0

sebenalern
sebenalern

Reputation: 2561

So one problem I see is you should be using the keyword this inside the constructor

this.$scope = $scope;

Another thing it is probably easier to stay away from classes and use functions:

class Login {
constructor($scope, $reactive, $state, myService) {
    console.log(myService.somevariable); //doesn't work
   }
}

Becomes:

angular
.module('name')
.service('myService', myService);

function myService () {
    this.somevariable = 'somevalue';
}

To me it seems a lot cleaner. Also another thing about ES6 classes is

ES6 Classes are not hoisted, which will break your code if you rely on hoisting

For more info see link.

Now here is the working code I came up with:

First we declare the module:

angular.module('name', []);

Next we register our service and then create the service definition:

angular
   .module('name')
   .service('myService', myService);

function myService () {
   this.somevariable = 'somevalue';
}

Next we do the same procedure for our controller and also we inject $scope and our service into it.

angular
   .module('name')
   .controller('Login', Login);

function Login($scope, myService) {
    $scope.someVar = myService.somevariable;
}

Last I registered our component:

angular
   .module('name')
   .component('my-html', {
   templateUrl: 'my-html.html',
   controller: Login
});

And that is it on the javascript side.

Here is my html code:

<!DOCTYPE html>
<html lang="en-us" ng-app='name'>
  <head>
      <script src="//code.angularjs.org/1.5.0-rc.1/angular.js"></script>
      <script src="controller.js"></script>
  </head>
  <body >
      <h ng-controller="Login">{{ someVar }}</h>
  </body>
</html>

I hope this helps!!

Upvotes: 5

Related Questions