jlembke jlembke - 4 months ago 11
AngularJS Question

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());
}

Answer

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;
}