1

I have a $http service that read a json file. I want to use modularization, but I don't know how to call my service in my controller and I don't know if my service is well written.

Here a jsFidlle : https://jsfiddle.net/aqbmdrvn/ .

Thanks!!!

/// <reference path="../../typings/angularjs/angular.d.ts" />
/// <reference path="../../typings/angularjs/angular-route.d.ts" />
/// <reference path="../app.ts" />  
/// <reference path="servicePets.ts" />
"use strict";

module AnimalPlanet {
    // pet interface
    export interface IPet {
        type: string;
        name: string;
        age: number;
        color: string;
        specialCare: boolean;
        availableForAdoption: boolean;
        ldAdoption: boolean;
        history: string;
        featured: boolean;
        newest: boolean;
        imageUrl: string;
    }

    export interface RootObject {
        pets: IPet[];
    }
    // pet controller with ui-grid
    export class petsCtrl implements RootObject {
        pets: IPet[];
        constructor(private $http: ng.IHttpService,public petsService,  private $scope: any, uiGridConstants: any, filterldAdoption: any) {
            $scope.pets = {};
            // ui grid option
            $scope.gridOptions = {
                enableSorting: true,
                enableFiltering: true,
                paginationPageSizes: [5, 10, 15],
                paginationPageSize: 5,
                onRegisterApi: (gridApi) => {
                    $scope.gridApi = gridApi;
                },
                columnDefs: [
                    {
                        name: 'type',
                        cellTooltip: true,
                        headerTooltip: true
                    },
                    {
                        name: 'name',
                        cellTooltip: true,
                        headerTooltip: true
                    },

                    {
                        name: 'age',
                        // filters: [{
                        //     condition: uiGridConstants.filter.GREATER_THAN,
                        //     placeholder: 'greater than'
                        // }, {
                        //         condition: uiGridConstants.filter.LESS_THAN,
                        //         placeholder: 'less than'
                        //     }
                        // ],
                        cellTooltip: true,
                        headerTooltip: true
                    },
                    {
                        name: 'color',
                        cellTooltip: true,
                        headerTooltip: true

                    },
                    {
                        name: 'specialCare',
                        cellTooltip: true,
                        headerTooltip: true
                    },
                    {
                        name: 'availableForAdoption',
                        cellTooltip: true,
                        headerTooltip: true
                    },
                    {
                        name: 'history',
                        cellTooltip: true,
                        headerTooltip: true
                    },
                    {
                        name: 'featured',
                        cellTooltip: true,
                        headerTooltip: true
                    },
                    {
                        name: 'newest',
                        cellTooltip: true,
                        headerTooltip: true
                    },
                    {
                        name: 'imageUrl',
                        cellTooltip: true,
                        headerTooltip: true,
                        enableFiltering: false,
                        enableHiding: false,
                        cellTemplate: "<img width=\"50px\" ng-src=\"{{grid.getCellValue(row, col)}}\" lazy-src>"
                    }
                ]
            };
            // read json using http service
            this.$http.get('/app/pets/pets.json').success((data) => { // pune te rog asta intr-un serviciu

                // fill ui grid using http service
                $scope.filterPets = data;
                var uiGridPets = [];
                angular.forEach($scope.filterPets, (item) => {
                    if (item.ldAdoption) {
                        uiGridPets.push(item);
                    }
                });

                $scope.gridOptions.data = uiGridPets;

                // filter for main page with 3 pets
                $scope.pets = data;
                $scope.quantity = 3;
                var featuredPets = [];
                var newestPets =[];
                angular.forEach($scope.pets, (item) => {
                    if (item.featured) {

                        featuredPets.push(item);

                    }
                    if(item.newest){
                        newestPets.push(item);
                    }

                });
                $scope.featuredPets = featuredPets;
                $scope.newestPets = newestPets;
           });
            $scope.fromService = petsService.weatherChange();
        }

    }

    petsCtrl.$inject = ['$http', '$scope', 'uiGridConstants', 'petsService'];
    app.controller("petsCtrl", petsCtrl);


}
/// <reference path="../../typings/angularjs/angular.d.ts" />
/// <reference path="../../typings/angularjs/angular-route.d.ts" />
/// <reference path="../app.ts" />  

"use strict";

module AnimalPlanet {
    export interface IPetsService {
        http: ng.IHttpService;
        uiGridConstants: any;
    }
    export class servicePets implements IPetsService {
       http: ng.IHttpService;
       uiGridConstants: any;
        constructor( $scope:any , $http: ng.IHttpService, uiGridConstants: any )
        {
             // read json using http service
            $scope.pets = {};
            this.http = $http;
        }
        public get() {
            this.http.get('/app/pets/pets.json').success((data) => { // pune te rog asta intr-un serviciu

                // fill ui grid using http service
                var filterPets = data;
                var uiGridPets = [];
                angular.forEach(filterPets, (item) => {
                    if (item.ldAdoption) {
                        uiGridPets.push(item);
                    }
                });

                var gridOptions.data = uiGridPets;

                // filter for main page with 3 pets
                var pets = data;

                var quantity = 3;
                var featuredPets = [];
                var newestPets =[];
                angular.forEach(pets, (item) => {
                    if (item.featured) {

                        featuredPets.push(item);

                    }
                    if(item.newest){
                        newestPets.push(item);
                    }

                });
                var featuredPets = featuredPets;
                var newestPets = newestPets;
            });
    }

    }

    servicePets.$inject = ['$http', '$scope', 'uiGridConstants'];
    app.service('servicePets', servicePets);

}
4
  • you are injecting petsService but its name is servicePets. Also make sure the constructor and $inject-array are in the same order. currently they aren't. I would suggest making $inject a static variable of the class, that way you can see the constructor and $inject next to each other Commented Jan 8, 2016 at 9:39
  • Also you can't inject $scope to a service. Commented Jan 8, 2016 at 9:41
  • Ok. You have right, but now how to call my service in my controller? I need to show all data from servicePets service to my controller in this empty variable $scope.pets = {}. Look at this updated fiddle : jsfiddle.net/Lzvo5ve7 . Thanks so much for help. Commented Jan 8, 2016 at 10:29
  • I'm not sure what you mean.. Call the function of the service? The function needs to return something. If it returns a promise, make sure you set the scope data in the success-callback of the promise Commented Jan 8, 2016 at 10:46

2 Answers 2

2

Here's what I use for boilerplate controller and factory:

Controller code:

declare var app: angular.IModule;

class MyController {
    static $inject = ['myService'];

    localData: IGetDataResult;

    constructor(private myService: MyService) {
        this.myService.getData('key1')
            .then(result => {
                this.localData = result.data;
            });
    }
}

app.controller('myController', MyController);

Factory code:

declare var app: angular.IModule;

interface IGetDataResult {
    field1: string;
}

class MyService {
    static $inject = ['$http'];

    constructor(private $http: angular.IHttpService) {
    }

    getData(key: string): angular.IHttpPromise<IGetDataResult> {
        return this.$http({
            method: 'POST',
            data: {
                key: key
            },
            url: '/WebService/GetData'
        });
    }
}

function MyServiceFactory($rootElement) : MyService {
    const inj = $rootElement.injector();
    return inj.instantiate(MyService);
}
app.factory('myService', ['$rootElement', $rootElement => MyServiceFactory($rootElement)]);

Some explanations:

  • The controller is straightforward enough, but note the usage of the static injection variable $inject. The order of elements in that array must correspond to the order of parameters in the constructor function.
  • My factory is instantiated by a factory function (pardon the pun). Note that I am injecting a dependency on $rootElement. I discovered that if I ever want to use $location I must use the injector instantiated on that $rootElement.
  • I am using a strongly typed return value on the $http call. This helps a lot for the obvious reasons.
  • Note that everything is definitely typed, except for $rootElement. There is no matching type for it in angular.d.ts that includes the injector() function.

One more thing, typescript lends itself to the controllerAs methodology. Meaning that you don't need to inject $scope into your controller, and in your html you must prepend the controller alias (the controllerAs value) before every scope expression. When doing it that way, you put all your scope variables and functions as members on your controller.

Sometimes you do need to inject $scope if you want to use $watch or $on, but there are a few gotchas there, with regards to this closure, but this is a topic for another post.

One gotcha with ui-grid is that if you use a string value for your gridoptions.data member, it must also include the controller alias prefix.

Sign up to request clarification or add additional context in comments.

Comments

0

To modularize your code, you want to refactor the $http call and its dependency injection out of the controller and into the service.

When you inject the service into the controller you need to account for the module "namespace". So, your $inject will look like: "AnimalPlanet.petsService". This is probably why you are having trouble invoking the service from your controller. It doens't look like it's wired properly.

I don't use $inject the way you are doing it. I follow this pattern:

// Dependencies for this controller.
static $inject = ["$q",
    "$location",
    "$window",
    "$scope",
    "$log",
    "common",
    "RL.SS.Portal.RLToday.Services.AroundTheIndustryService",
    "RL.SS.Portal.RLToday.Services.LocationFilterService"];

That's inside the class definition itself. I don't know if that's necessarily more accurate, but you might find it useful.

In the controller's constructor, you don't need to (and probably should not) make the petservice reference public, but that's not really your problem, just a style thing.

Once you get the injection right, you can do this from your controler:

this.petsService.Get().then( () => { /* success */ }, () => { /* fail */});

HTH.

(this is my first attempt at answering a stack overflow question, so if anyone wants to advise me on how to do better, please feel free to do so).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.