Search code examples
javascriptionic4angular8

TypeError: Cannot read property '0' of null at SelectedDateService.ngOnInit


I am working on angular 8 and ionic 4 project but when I run the project in device it gives error Can not read property '0' of null at SelectedDateService.ngOnInit().In this code we can move old code from version ionic3 and angular7 to new code with version inic4 and angular 8 ,but I can't understand why this error comes and how to solve it. Can any body guide me?

SelectedDateService

import { Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import * as moment from 'moment'

@Injectable({
  providedIn: 'root'
})
export class SelectedDateService {
  selectedProfile: any;
  timeObj: any;
  dateYesterday: any;
  dateLastMonthTo: any;
  dateLastWeekTo: any;
  dateThisMonthTo: any;
  dateLast30DaysTo: any;
  dateLastMonthFrom: any;
  dateLastWeekFrom: any;
  dateThisMonthFrom: any;
  dateLast30DaysFrom: any;
  usersProfiles: any;
  selectedDate: any;
  selectedDateLabel: any;
  providerObj: any = {}

  lastWeek: any;
  lastMonth: any;
  yesterday: any;
  thisMonth: any;
  last30Days: any;
  customRange: any;
  constructor(translate:  TranslateService ) {
    translate.get("LAST_WEEK").subscribe(value => {this.lastWeek = value})
        translate.get("LAST_MONTH").subscribe(value => {this.lastMonth = value})
        translate.get("YESTERDAY").subscribe(value => {this.yesterday = value})
        translate.get("THIS_MONTH").subscribe(value => {this.thisMonth = value})
        translate.get("LAST_30_DAYS").subscribe(value => {this.last30Days = value})
        translate.get("CUSTOM_RANGE").subscribe(value => {this.customRange = value})
        this.ngOnInit();
   }
   ngOnInit() : void
   {
    this.usersProfiles = JSON.parse(window.localStorage.getItem('profiles'));
    this.selectedProfile = JSON.parse(window.localStorage.getItem('lastUsedProfile')) || this.usersProfiles[0];
    this.timeObj =  this.setTimeObj();
   }
   setTimeObj() {
    let obj = {
      0: {
          'label': this.lastWeek,
          'timeTo': this.dateLastWeekTo,
          'timeFrom': this.dateLastWeekFrom,
          'id': 'last-week'
        },
        1: {
          'label': this.yesterday,
          'timeFrom': this.dateYesterday,
          'id': 'yesterday'
        },
        2: {
          'label': this.last30Days,
          'timeTo': this.dateLastWeekTo,
          'timeFrom': this.dateLastWeekFrom,
          'id': 'last-30-days'
        },
        3: {        
          'label': this.lastMonth,
          'timeTo': this.dateLastMonthTo,
          'timeFrom': this.dateLastMonthFrom,
          'id': 'last-month'
        },
        4: {        
          'label': this.thisMonth,
          'timeTo': this.dateThisMonthTo,
          'timeFrom': this.dateThisMonthFrom,
          'id': 'this-month'
        }
    };
    return obj
}

getTimeVariables() {
    let lan = window.navigator.language;
    if (lan.includes('ES')){
       moment.locale('ES');
    } else{
       moment.locale('EN');
    }
    let month = (moment(Date.now()).month()) != 10 && (moment(Date.now()).month()) != 11 && (moment(Date.now()).month()) != 12 ? '0' : '';
    let monthNow = (moment(Date.now()).month() + 1) != 10 && (moment(Date.now()).month() + 1) != 11 && (moment(Date.now()).month() + 1) != 12 ? '0' : '';
    let startDate = moment(Date.now()).year().toString() + month + moment(Date.now()).month().toString() + '01';
    this.dateThisMonthTo = moment(Date.now() - 1 * 24 * 3600 * 1000).format('DD-MMMM');
    this.dateThisMonthFrom = moment(moment(Date.now()).year().toString() + monthNow + (moment(Date.now()).month() + 1 ).toString() + '01').format('DD-MMMM');
    this.dateYesterday =  moment(Date.now() - 1 * 24 * 3600 * 1000).format('DD-MMMM');  
    this.dateLastMonthTo = moment(startDate).endOf('month').format('DD-MMMM');
    this.dateLastMonthFrom = moment(moment(Date.now()).year().toString() + month + moment(Date.now()).month().toString() + '01').format('DD-MMMM');
    this.dateLastWeekTo = moment(Date.now() - 1 * 24 * 3600 * 1000).format('DD-MMMM');
    this.dateLastWeekFrom = moment(Date.now() - 6 * 24 * 3600 * 1000).format('DD-MMMM');
    this.dateLast30DaysTo = moment(Date.now() - 1 * 24 * 3600 * 1000).format('DD-MMMM');
    this.dateLast30DaysFrom = moment(Date.now() - 31 * 24 * 3600 * 1000).format('DD-MMMM');
 }


/*
** Returns data object of selected time
*/
getDateObj(time) {
    let dateArr = [];
    let dateFrom;
    let dateTo;
    let monthNow = (moment(Date.now()).month() + 1) != 10 && (moment(Date.now()).month() + 1) != 11 && (moment(Date.now()).month() + 1) != 12 ? '0' : '';

    if (time == 'this-month') {
      dateFrom = moment(Date.now()).year().toString() + monthNow + (moment(Date.now()).month() +1).toString() + '01';
      dateTo = moment(Date.now() - 1 * 24 * 3600 * 1000).format('YYYYMMDD');
    } else if (time == 'yesterday') {
      dateFrom = moment(Date.now() - 1 * 24 * 3600 * 1000).format('YYYYMMDD');
      dateTo =  moment(Date.now() - 1 * 24 * 3600 * 1000).format('YYYYMMDD');
    } else if (time == 'last-month') {
      dateFrom = moment(moment().subtract(1, 'month')).format('YYYYMM').toString() + '01';
      dateTo = moment(moment().subtract(1, 'month').endOf('month')).format('YYYYMMDD');
    } else if (time == 'last-30-days') {
      dateFrom = moment(Date.now() - 31 * 24 * 3600 * 1000).format('YYYYMMDD');
      dateTo =  moment(Date.now() - 1 * 24 * 3600 * 1000).format('YYYYMMDD');
    } else if (time == 'last-week') {
        dateFrom = moment(Date.now() - 7 * 24 * 3600 * 1000).format('YYYYMMDD');
        dateTo =  moment(Date.now() - 1 * 24 * 3600 * 1000).format('YYYYMMDD');
    } else if (time == 'custom-range') {
      dateFrom = moment(JSON.parse(window.localStorage.getItem('customRange'))[0]).format();
      dateTo = moment(JSON.parse(window.localStorage.getItem('customRange'))[1]).format();
    } else {
      dateFrom = moment(Date.now() - 7 * 24 * 3600 * 1000).format('YYYYMMDD');
        dateTo =  moment(Date.now() - 1 * 24 * 3600 * 1000).format('YYYYMMDD');
    }
    dateArr.push(dateFrom, dateTo);
    return dateArr
}

/*
** Returns value of selected date
*/

getSelectedDate(time) {
  let lan = window.navigator.language;
    let dateArr;
    let dateFrom;
    let dateTo;
  let monthNow = (moment(Date.now()).month() + 1) != 10 && (moment(Date.now()).month() + 1) != 11 && (moment(Date.now()).month() + 1) != 12 ? '0' : '';
  if (lan.includes('ES')){
      moment.locale('ES');
  } else{
      moment.locale('EN');
  }

    if (time == 'this-month') {
        dateFrom = moment(moment(Date.now()).year().toString() + monthNow + (moment(Date.now()).month() +1).toString() + '01').format('DD-MMMM');
        dateTo = moment(Date.now() - 1 * 24 * 3600 * 1000).format('DD-MMMM');
    } else if (time == 'yesterday') {
        dateFrom = moment(Date.now() - 1 * 24 * 3600 * 1000).format('DD-MMMM');
        dateTo =  moment(Date.now() - 1 * 24 * 3600 * 1000).format('DD-MMMM');
    } else if (time == 'last-month') {
        dateFrom = '01-' + moment(moment().subtract(1, 'month')).format('MMMM').toString();
        dateTo = moment(moment().subtract(1, 'month').endOf('month')).format('DD-MMMM'); 
    } else if (time == 'last-30-days') {
        dateFrom = moment(Date.now() - 31 * 24 * 3600 * 1000).format('DD-MMMM');
        dateTo =  moment(Date.now() - 1 * 24 * 3600 * 1000).format('DD-MMMM');
    } else if (time == 'last-week') {
        dateFrom = moment(Date.now() - 7 * 24 * 3600 * 1000).format('DD-MMMM');
        dateTo =  moment(Date.now() - 1 * 24 * 3600 * 1000).format('DD-MMMM');
    } else if (time == 'custom-range') {
      dateFrom = moment(JSON.parse(window.localStorage.getItem('customRange'))[0]).format('DD MMMM');
      dateTo = moment(JSON.parse(window.localStorage.getItem('customRange'))[1]).format('DD MMMM');
    } else {
      dateFrom = moment(Date.now() - 7 * 24 * 3600 * 1000).format('DD-MMMM');
        dateTo =  moment(Date.now() - 1 * 24 * 3600 * 1000).format('DD-MMMM');
    }           
    dateArr = dateFrom + ' - ' + dateTo;
    return dateArr
}
}

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy, RouterModule } from '@angular/router';

import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { LayoutComponent } from './components/layout/layout.component';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { AngularFireModule } from '@angular/fire';
import { AngularFirestoreModule } from '@angular/fire/firestore';

import { Firebase } from "@ionic-native/firebase/ngx";
import { UniqueDeviceID } from '@ionic-native/unique-device-id/ngx';
import { Device } from '@ionic-native/device/ngx';
import { TwitterConnect } from '@ionic-native/twitter-connect/ngx';
import { Facebook } from '@ionic-native/facebook/ngx';
import { WelcomePage } from './pages/welcome/welcome.page';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { InAppBrowser } from '@ionic-native/in-app-browser/ngx';


@NgModule({
  declarations: [
    AppComponent,
    LayoutComponent,
    WelcomePage
  ],
  entryComponents: [],
  imports: [
    CommonModule,
    FormsModule,
    ReactiveFormsModule,
    BrowserModule,
    HttpClientModule, 
    AngularFireModule.initializeApp(firebaseConfig),
    AngularFirestoreModule,

    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: createTranslateLoader,
        deps: [HttpClient]
      }
    }),
    IonicModule.forRoot(),
    AppRoutingModule,
  ],
  providers: [
    StatusBar,
    SplashScreen,
    Firebase,
    UniqueDeviceID,
    Device,    
    TwitterConnect,
    Facebook,
    InAppBrowser,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }


export function createTranslateLoader(http: HttpClient) {
  return new TranslateHttpLoader(http);
}

Solution

  • SelectedDateService is probably being run at a different place than you think, as it is a service that's created injected. This means that.

    It could also be that you have this bug everywhere, not just testing on the device, but your browser already has the values saved. Try wiping your cache and reloading it in the browser you will probably see the same error.

    You need to consider the chance of encountering the initial empty data set at first load, as well as existing users.

    In this line here:

    this.usersProfiles = JSON.parse(window.localStorage.getItem('profiles'));
    

    You need to either - find a way to guarantee that it has a value, or change it to something like:

    this.usersProfiles = JSON.parse(window.localStorage.getItem('profiles') || { /* some default json */ });
    

    Also, consider using Ionic Storage instead of using localStorage directly as it offers better cross device/platform compatibility: