jlembke
jlembke

Reputation: 13517

Why is this shared Angular service data not showing up?

I'm new to Angular, and my guess is I don't understand $resource and promises enough.

I'm trying to create a shared data scenario where I have a retrieval service that gets data fresh from a web api, and a shared service which my controllers can bind to for working with the data.

However, the data I'm expecting to display in the controller line vm.lines = sharedService.getLines(this.id); never gets displayed even though I can see that the web api is delivering the data to the retrievalService.

Can anyone nudge me in the right direction here?

Data Retrieval service:

module services {
    "use strict";

    export interface IRetrievalService {
            getLines(id: string): ng.resource.IResourceClass<IResource>;
        }

    interface IResource extends ng.resource.IResource<app.ILine> { }

    export class RetrievalService implements IRetrievalService {

        static $inject = ['$resource'];
        constructor(private $resource: ng.resource.IResourceService) {

        }

        getLines(id: string): angular.resource.IResourceClass<IResource> {
            return this.$resource("api/myUrl/?id=" + id);
        }
    }

    angular
        .module("services")
        .service("app.services.retrievalService", RetrievalService );
}

Shared Service

module services {
    "use strict";

    export interface ISharedService {
        _lines: app.ILine[];
        getLines(id: string): app.ILine[];
    }

    export class SharedService implements ISharedService {
        _lines: app.ILine[];

        static $inject = ["app.services.retrievalService"];
        constructor(private dataService: app.services.DataService) {

        }

        getLines(id: string): app.ILine[] {
            if (!this._lines) {
                var resource = this.dataService.getLines(id);
                resource.query((data: app.ILine[]) => {
                    this._lines = data
                });
            }

            return this._lines;
        }
    }

    angular
        .module("services")
        .service("app.services.sharedService", SharedService);
}

Controller/Component

module app {
    "use strict";

    interface ILinesScope {
        id: string;
        lines: app.ILine[];
    }

    class LinesComponentController implements ILinesScope {
        id: string;
        lines: app.ILine[];

        static $inject = ["app.services.sharedService"];
        constructor(private sharedService: services.SharedService) {
            var vm = this;

            vm.id = "5";
            vm.lines = sharedService.getLines(this.id);
        }
    }

    class LinesComponent implements ng.IComponentOptions {
        templateUrl = "app/Lines.html";
        controllerAs = "vmLines";
        controller = ["app.services.sharedService", LinesComponentController];
    }

    angular.module("app")
        .component("myLines", new LinesComponent());
}

html

<div>
    <table>
        <thead>
        <tr>
            <th>column 1</th>
            <th>column 2</th>
        </tr>
        </thead>
        <tbody>
        <tr ng-repeat="line in vmLines.lines">
            <td>{{line.col1}}</td>
            <td>{{line.col2}}</td>
        </tr>
        </tbody>
    </table>
</div>

I'm trying to follow advice from John Papa at for how to do shared data across controllers.

UPDATE WITH FULL SOLUTION Here are the changes I had to make to get this to work:

Shared Service:

module services {
    "use strict";

    export interface ISharedService {
        //_lines: app.ILine[];
        _lines: ng.resource.IResourceArray<ng.Resource.IResource<ILine>>
        //getLines(id: string): app.ILine[];
        getLines(id: string): ng.resource.IResourceArray<ng.Resource.IResource<ILine>>

    }

    export class SharedService implements ISharedService {
        //_lines: app.ILine[];
        _lines: ng.resource.IResourceArray<ng.Resource.IResource<ILine>>

        static $inject = ["app.services.retrievalService"];
        constructor(private dataService: app.services.DataService) {

        }

        //getLines(id: string): app.ILine[] {
        getLines(id: string): ng.resource.IResourceArray<ng.Resource.IResource<ILine>> {
            var vm = this;
            if (!this._lines) {
                var resource = this.dataService.getLines(id);
                return resource.query();
                //resource.query((data: app.ILine[]) => {
                //    this._lines = data
                //});
            }

            return this._lines;
        }
    }

    angular
        .module("services")
        .service("app.services.sharedService", SharedService);
}

Controller/Component:

module app {
    "use strict";

    interface ILinesScope {
        id: string;
        //lines: app.ILine[];
        lines: ng.resource.IResourceArray<ng.Resource.IResource<ILine>>;
    }

    class LinesComponentController implements ILinesScope {
        id: string;
        //lines: app.ILine[];
        lines: ng.resource.IResourceArray<ng.Resource.IResource<ILine>>;

        static $inject = ["app.services.sharedService"];
        constructor(private sharedService: services.SharedService) {
            var vm = this;

            vm.id = "5";
            vm.lines = sharedService.getLines(this.id);
        }
    }

    class LinesComponent implements ng.IComponentOptions {
        templateUrl = "app/Lines.html";
        controllerAs = "vmLines";
        controller = ["app.services.sharedService", LinesComponentController];
    }

    angular.module("app")
        .component("myLines", new LinesComponent());
}

Upvotes: 0

Views: 83

Answers (2)

Brendon Colburn
Brendon Colburn

Reputation: 1912

when you breakpoint this._lines = data does debugger hit it? This kind of reminds me of the common issue where this is undefined. You may need to do var self = this outside of the callback function and then say self._lines = data

Upvotes: 1

DerekMT12
DerekMT12

Reputation: 1349

I think it's because you need to return $resource.query from your service.

getLines(id: string): app.ILine[] {
   if(!this._lines) {
      var resource = this.dataService.getLines(id);
      return resource.query((data: app.ILine[]) => {
         this._lines = data
      });
   }
   return this._lines;
}

Upvotes: 1

Related Questions