So I have two classes defined for this project:
CustomerJob
export class CustomerJob {
partNumber?: string;
revision?: string;
description?: string;
dueDate?: Date;
customer?: string;
purchaseOrderNumber?: string;
quantityDue?: number;
quantityShipped?: number;
salesOrderNumber?: number;
salesOrderLineNumber?: number;
salesOrderLineLotNumber?: number;
itemID?: number;
salesOrderCreateDate?: Date;
salesOrderLineCreateDate?: Date;
salesOrderLineLotCreateDate?: Date;
progress?: number;
shipVia?: string;
status?: string;
customDescription?: string;
shippingLocation?: string;
documents?: DocumentFile[];
openQuantity?: number = 0;
}
DocumentFile
export class DocumentFile {
id?: number;
url?: string;
fileName?: string;
extension?: string;
extensionWithoutPeriod?: string;
isImageFile: boolean = false;
setup () {
console.warn('doing setup for document');
// get name of file (filename.extension). need to remove all the \\ stuff basically
let _stringArray = this.url?.split('\\');
// the last one in this split is the filename and extension
let _filenameWithExtension = _stringArray![_stringArray!.length - 1];
// split this by period
let _filenameSplit = _filenameWithExtension.split('.');
// first one in array is the filename
this.fileName = _filenameSplit![0];
// second is extension
this.extensionWithoutPeriod = _filenameSplit![1];
this.extension = '.' + this.extensionWithoutPeriod;
}
}
I have a service that looks like this:
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { firstValueFrom } from 'rxjs';
import { CustomerJob, DocumentFile } from '../dataModels/data-models';
import { LoginService } from '../services/login.service';
@Injectable({
providedIn: 'root'
})
export class JobService {
constructor(private http: HttpClient, private loginService: LoginService) { }
jobs?: CustomerJob[] = [];
async getCustomerJobs () {
let headers = new HttpHeaders().set('APIKey', this.loginService.loginInformation!.apiKey);
try {
this.jobs = await firstValueFrom(this.http.get<CustomerJob[]>('https://XXXXX', { headers: headers }));
// do some modifications to them
this.jobs.forEach(function (j) {
// quantity
if (j.quantityDue != undefined && j.quantityShipped != undefined) {
j.openQuantity = j.quantityDue - j.quantityShipped;
}
// document stuff
if (j.documents != undefined) {
j.documents.forEach(d => {
// console.warn('setting up F');
if (d == undefined) {
console.warn('this document is undefined');
}
else {
//d = Object.assign(d, j.documents[i]);
console.warn('this document is defined: ' + d.id + ', ' + d.url);
d.setup();
console.warn(d.fileName);
}
});
}
else {
console.warn('this one DOES NOT have documents');
}
});
}
catch (error: any) {
console.error('CATCH ERROR: ' + error.message);
}
return this.jobs;
}
}
This is the error I get in the console via the TryCatch:
d.setup is not a function
The important thing here though is that it IS properly printing out some info in the line right before it:
console.warn('this document is defined: ' + d.id + ', ' + d.url);
So eventually I figured out that the problem must just be that "d" isn't actually a DocumentFile type. I can't figure out why since the array is typed specifically as a DocumentFile array in the CustomerJob class. So at some point, I'm guessing when it's creating the array of CustomerJobs through the Http.Get it's just transforming the specifically typed DocumentFile array into an array of anonymous objects or whatever.
I know this is true because if I change the code to look like this it works fine:
j.documents.forEach(d => {
// console.warn('setting up F');
if (d == undefined) {
console.warn('this document is undefined');
}
else {
let doc: DocumentFile = new DocumentFile();
Object.assign(doc, d);
console.warn('this document is defined: ' + doc.id + ', ' + doc.url);
doc.setup();
console.warn(doc.fileName);
}
});
I come from using C#, so I always have trouble with loosely typed languages like JavaScript. It's very frustrating. Thank you in advance for your help.