This question is locked. New answers and comments are not allowed.
In my NativeScript angular project I am using a radlistview to display a list of messages from a firebase backend. In Android the list item is displaying correctly however in IOS I am getting the following error and the application is terminated:
CONSOLE WARN file:///app/tns_modules/tns-core-modules/application/application.js:212:26: Fatal JavaScript exception - application has been terminated.
file:///app/tns_modules/nativescript-telerik-ui/listview/listview.js:1311:20: JS ERROR TypeError: undefined is not an object (evaluating 'type.toLowerCase')
I am using the latest version of the nativescript-telerik-ui 3.1.0 and tns 3.2.
My code for the template, component and service is as follows, Please let me know what I need to change.
Component.html
<
GridLayout
rows
=
"*"
class
=
"m-x-10"
>
<
RadListView
[items]="this.messagesForView" [itemTemplateSelector]="templateSelector">
<
ng-template
tkTemplateKey
=
"testPrint"
let-item
=
"item"
>
<!--For testPrint messages-->
<
GridLayout
rows
=
"auto auto"
columns
=
"auto *"
>
<
Label
row
=
"0"
col
=
"0"
text
=
""
class
=
"fa p-t-4 m-y-5"
></
Label
>
<
Label
row
=
"0"
col
=
"1"
[text]="'Your item ' + item.testName + 'is ready for download at ' + item.testLink"></
Label
>
<
Label
row
=
"1"
col
=
"1"
text
=
"11:50"
horizontalAlignment
=
"right"
></
Label
>
</
GridLayout
>
</
ng-template
>
<
ng-template
tkTemplateKey
=
"otherMessage"
let-item
=
"item"
>
<!--For Other Messages-->
<
GridLayout
rows
=
"auto auto"
columns
=
"auto *"
>
<
Label
row
=
"0"
col
=
"0"
text
=
""
class
=
"fa p-t-4 m-y-5"
></
Label
>
<
Label
row
=
"0"
col
=
"1"
[text]="item.body"></
Label
>
<
Label
row
=
"1"
col
=
"1"
text
=
"13:10"
horizontalAlignment
=
"right"
></
Label
>
</
GridLayout
>
</
ng-template
>
</
RadListView
>
</
GridLayout
>
Component.ts
import { AfterContentInit, Component, OnInit, OnDestroy } from
"@angular/core"
;
import { NavigationExtras, Router } from
"@angular/router"
;
import { RouterExtensions } from
"nativescript-angular"
;
import { android } from
"application"
;
// THis is to import application for handleing back button.
import { Subscription } from
"rxjs/Rx"
;
import { Page } from
"ui/page"
;
import { Location } from
"@angular/common"
;
//import ui elements
import scrollViewModule = require(
"ui/scroll-view"
);
// import htmlViewModule = require("ui/html-view");
import { ListViewEventData, RadListView } from
"nativescript-telerik-ui/listview"
;
//This import is for rad list and event data on radList.
import { topmost } from
"ui/frame"
;
//To catch the rad list component as view.
import { View } from
"ui/core/view"
;
//To use a component as a View.
import { isTablet } from
"../shared/device-constant/device.constant"
;
import { UserStatusService } from
"../services/userStatus.service"
;
import { FirebaseMessagingService } from
"../services/firebase-messaging.service"
;
import { AndroidBAckButtonHandlerService } from
"../services/androidBackButtonHandler.service"
;
import { ObservableArray } from
"data/observable-array"
;
@Component({
moduleId: module.id,
selector:
"messaging"
,
styleUrls: [(isTablet ?
'../tablet.css'
:
'../phone.css'
)],
templateUrl:
"./messaging.component.html"
,
})
export class MessagingComponent implements OnInit, OnDestroy {
uid: string;
private backButtonHandler: Subscription;
public isTablet: boolean;
public messagesForView: ObservableArray<any>;
private _templateSelector: (item: any, index: number, items: any) => string;
public messagesSubscriber: Subscription;
constructor(private router: Router,
private routerExtensions: RouterExtensions,
private location: Location,
private userStatusService: UserStatusService,
private firebaseMessagingService: FirebaseMessagingService,
private page: Page,
private androidBAckButtonHandlerService: AndroidBAckButtonHandlerService) {
}
public ngOnInit() {
this
.messagesForView =
new
ObservableArray();
this
._templateSelector =
this
.templateSelectorFunction;
this
.page.actionBarHidden =
true
;
this
.messagesSubscriber =
this
.firebaseMessagingService.messagesReceived.subscribe((currentMessages) => {
this
.messagesForView.push.apply(
this
.messagesForView, currentMessages);
});
this
.firebaseMessagingService.getMessageFromFirebase();
if
(
this
.firebaseMessagingService.getMessages() !== undefined) {
this
.messagesForView = JSON.parse(
this
.firebaseMessagingService.getMessages());
}
else
{
const welcomeMessage = {
type:
"otherMessage"
,
testName:
"Trial Test"
,
testLink:
"Trial Link"
,
title:
"Welcome"
,
body:
"Hello"
,
};
this
.messagesForView.push(welcomeMessage);
}
//Subscribing android back button event emitter.
this
.backButtonHandler =
this
.androidBAckButtonHandlerService.detailTestBackHandler.subscribe((status) => {
console.log(
"Back button pressed on detail test component and the status is: "
+ JSON.stringify(status));
});
}
get dataItems(): ObservableArray<any> {
return
this
.messagesForView;
}
get templateSelector(): (item: any, index: number, items: any) => string {
return
this
._templateSelector;
}
set templateSelector(value: (item: any, index: number, items: any) => string) {
this
._templateSelector = value;
}
public templateSelectorFunction = (item: any, index: number, items: any) => {
return
item.messageType;
}
public ngOnDestroy() {
if
(android) {
this
.backButtonHandler.unsubscribe();
console.log(
"Back button handler is unsubscribed !!"
);
}
}
}
Service.ts
import { Injectable, EventEmitter, NgZone } from
"@angular/core"
;
import firebase = require(
"nativescript-plugin-firebase"
);
import { Observable } from
'rxjs/Observable'
;
import { BehaviorSubject } from
'rxjs/BehaviorSubject'
;
import
'rxjs/add/operator/share'
;
import { setString, getString, remove } from
"application-settings"
;
import { ObservableArray } from
"tns-core-modules/data/observable-array"
;
@Injectable()
export class FirebaseMessagingService {
public messagesReceived: BehaviorSubject<any> =
new
BehaviorSubject({});
constructor(
private ngZone: NgZone,
) {
}
// Get the User's messages
public getMessageFromFirebase(): void {
console.log(
"I have come to get my messages"
);
firebase.addOnMessageReceivedCallback(
(message) => {
if
(message) {
//create message object
let currentMessages =
new
ObservableArray();
const newMessage =
this
.createMessageObject(message);
if
(
this
.getMessages() !== undefined) {
currentMessages.push.apply(currentMessages, JSON.parse(
this
.getMessages()));
}
console.log(
"Current Messages is "
+ currentMessages);
currentMessages.push(newMessage);
console.log(
"After pushing Current Messages is "
+ currentMessages);
this
.setMessages(JSON.stringify(currentMessages));
this
.messagesReceived.next(currentMessages);
}
},
);
}
createMessageObject(message) {
console.log(
"Message Data type is"
+ message.type);
console.log(
"Type of the message type is"
+
typeof
(message.type));
if
(message.type ===
"testPrint"
) {
const messageObject = {
messageTestName: message.title,
messageType: message.type,
messageBody: message.body,
messageTestLink: message.testLink,
};
return
messageObject;
}
else
{
const messageObject = {
messageTitle: message.title,
messageType: message.type,
messageBody: message.body,
};
return
messageObject;
}
}
setMessages(storedMessages: string) {
setString(
'storedMessages'
, (storedMessages));
}
getMessages() {
return
getString(
'storedMessages'
);
}
removeMessages() {
remove(
'storedMessages'
);
}
}
Thank you.