I am working on a project which will need to migrate all instances of the old Http to utilize the new HttpClient provided by Angular. But I am having issues with the migration of one of my methods. I get this error ERROR TypeError: Cannot read properties of null (reading 'text') at main.js
Old Method:
ngAfterViewInit(): void {
var header = this.header;
if (header == null)
return;
var params = new URLSearchParams();
params.set('manufacturerCode', `${header.manufacturerCode || 0}`);
params.set('typeCode', `${header.typeCode || 0}`);
params.set('typeRevisionCode', `${header.typeRevisionCode || 0}`);
params.set('protocol', `${header.protocol || 0}`);
params.set('serialNumber', header.serialNumber);
params.set('tag', header.tag);
this.http.get(`./api/devices/device-icon`, { search: params }).pipe(map((response: Response) => response.text())).subscribe(data => {
let source: string;
if (data != null && data.length > 0)
source = `data:image/x-icon;base64,${data}`;
else
source = './assets/Default_Device_Icon.ico'; // use the default device icon
this.renderer.setElementAttribute(this.elementRef.nativeElement, 'src', source);
this.invisible = false;
});
}
New Method:
ngAfterViewInit(): void {
var header = this.header;
if (header == null)
return;
var params = new HttpParams();
params.set('manufacturerCode', `${header.manufacturerCode || 0}`);
params.set('typeCode', `${header.typeCode || 0}`);
params.set('typeRevisionCode', `${header.typeRevisionCode || 0}`);
params.set('protocol', `${header.protocol || 0}`);
params.set('serialNumber', header.serialNumber);
params.set('tag', header.tag);
this.httpClient.get(`./api/devices/device-icon`, { params, responseType: 'text'})
.pipe(map((response: any) => response.text()))
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(async data => {
let source: string;
if (data != null && (await data).length > 0)
source = `data:image/x-icon;base64,${data}`;
else
source = './assets/Default_Device_Icon.ico'; // use the default device icon
this.renderer.setAttribute(this.elementRef.nativeElement, 'src', source);
this.invisible = false;
});
}
CodePudding user response:
This is why you don't cast to type any
: ) . If you remove that, the compiler will tell you that response.text()
is not a function, and hovering over the response tells you it is already a string. You've already supplied the responseType
as text
so that is what you get back.
this.httpClient.get(`./api/devices/device-icon`, { params, responseType: 'text'})
// Removed the map call
.pipe(takeUntil(this.ngUnsubscribe))
Also, the way you set HttpParams
is doing nothing. set
returns a value rather than modifying in place. You can do it like this:
const params = new HttpParams()
.set('manufacturerCode', `${header.manufacturerCode || 0}`)
.set('typeCode', `${header.typeCode || 0}`)
.set('typeRevisionCode', `${header.typeRevisionCode || 0}`)
.set('protocol', `${header.protocol || 0}`)
.set('serialNumber', header.serialNumber)
.set('tag', header.tag);
No need to use async
await
inside a subscribe callback. And please just use if (data)
, this will be false for null
, undefined
, empty string, NaN
, and the number 0
(the string
"0"
is true). https://developer.mozilla.org/en-US/docs/Glossary/Truthy
.subscribe((data) => {
let source: string;
if (data) source = `data:image/x-icon;base64,${data}`;
else source = './assets/Default_Device_Icon.ico'; // use the default device icon
or simply use the ternary operator
const source = data
? `data:image/x-icon;base64,${data}`
: './assets/Default_Device_Icon.ico'; // use the default device icon