UPDATE
I've put a return
after a console log and determined that the issue isn't the Promise -- it's reading that just fine. At the line I highlight in the code below, this.contentItems = cpl.ary as ContentItem[];
is where the error is occuring. I've verified that cpl
is an object with one property, ary
, which is an array of 4 items. It displays in the console log fine. But when I try to get the ary
property as ContentItem[]
it comes up with null
and tries to assign it to my empty Content[]
on the left-hand side. So this is purely a casting or other type assignment issue. I'll change the subject of this question once I've found an answer.
My problem is that this.contentItems
gets set to null in the then
methods in content-display.component.ts.
The JSON I'm consuming is this:
{ "ary":[
{
"id": "1",
"name": "Test Project",
"nextDate": "2016-12-01T16:00:00",
"dateDescription": "ends",
"contentType": "project",
"link": "http://google.com",
"topics": ["1"]
},
{
"id": "3",
"name": "Dummy Article",
"nextDate": "2016-12-21T00:00:00",
"dateDescription": "expires",
"contentType": "article",
"link": "http://msn.com",
"topics": ["2"]
}
]}
In my content-item.service.ts:
getContentItems(): Promise<ContentPayload> {
if( window.location.hostname === "localhost" )
return Promise.resolve( CONTENTITEMS );
else
return this.http.get( this.contentUrl )
.toPromise()
.then( (response) => { return response.json() } )
.then( (data) => { return data as ContentPayload })
.catch( this.handleError );
}
And back in my content-display.component.ts
private contentItems: ContentItem[] = [];
getContentItems(): void {
this.contentItemService.getContentItems()
.then( (contentPayload) => this.getArrayFromPayload )
.then( this.getSelectOptions );
}
getArrayFromPayload( cpl: ContentPayload ): void {
this.contentItems = cpl["ary"];
/********** above, this.contentItems is set to null ************/
this.filteredItems = this.contentItems;
}
ContentPayload:
export class ContentPayload {
ary: any[];
}
ContentItem:
export class ContentItem {
id: string;
name: string;
nextDate: Date;
dateDescription: string;
contentType: string;
link: string;
isClicked?: boolean = false;
topics: string[];
}
This one is included for completeness. What it does isn't important, the error occurs above.
getSelectOptions( ): void {
// return TOPICMAP;
var topicMap: Topic[] = TOPICMAP;
var filteredTopicMap: Topic[] = [];
var uniqueValues: string[] = this.makeContentSet( this.getTopicIDs( this.contentItems ) );
for( var i = 0; i < uniqueValues.length; i++ ) {
filteredTopicMap.push( this.getTopicWithID( topicMap, uniqueValues[i] ) );
}
this.selectOptions = filteredTopicMap;
}
And my template for this component (inconsistencies in style and use of "this" will be cleaned up eventually. And did you know iPads don't have back-ticks?):
template: `
<h2>{{title}}</h2>
<div>Maximum of 20 items</div>
<div>Order:
<span [class.clicked]="latestOldest==='latest'" (click)="mySort('latest')">latest first</span>
|
<span [class.clicked]="latestOldest==='oldest'" (click)="mySort('oldest');">oldest first</span>
</div>
<div>
Filters:
<ng-select
[options] = "this.selectOptions"
[multiple] = "this.showMultiple"
placeholder = "Select topics"
[allowClear] = "true"
theme = "default"
(selected) = "onSelected( $event )"
(deselected) = "onDeselected( $event )">
</ng-select>
<ul>
<li *ngFor="let contentItem of filteredItems"
(click)="onClick(contentItem)"
class="{{contentItem.contentType}}"
[class.clicked]="contentItem.isClicked">
<h3>{{contentItem.name}}</h3>
<div>{{ contentItem.contentType | uppercase }} {{ contentItem.dateDescription}}
{{ contentItem.nextDate.toGMTString() | date:'mediumDate' }}
{{ (contentItem.contentType !== "article")? (contentItem.nextDate | date:'shortTime'): '' }}
</div>
</li>
</ul>
</div>
`