[ionic-v4] Handling null with 2-Way Binding

I’m new to ionic and am trying to put together a simple app that has a simple data input screen using sqlite. I’m testing on Android, using Chrome to debug. I’ve implemented a database service based on the tutorial here:

https://devdactic.com/ionic-4-sqlite-queries/

However, when I initially navigate to the input screen I get this error:

PatientPage.html:15 ERROR TypeError: Cannot read property 'first_name' of null 
  at Object.eval [as updateDirectives] (PatientPage.html:15)

Here’s the offending line in my html:

<ion-input name="inp_name" [(ngModel)]="patient.first_name" placeholder="Enter first name"></ion-input>

In my DatabaseService class, I define a Patient object:

export interface Patient {
  id: number,
  first_name: string,
  surname: string,
  gender: string,
  dob: string
}

Then I initialise a BehaviorSubject like this:

patient = new BehaviorSubject<Patient | undefined>(undefined);

I have a getPatient method:

getPatientById(id): Promise<Patient> {
  return this.database.executeSql('SELECT * FROM patient WHERE id = ?', [id]).then(data => {

    return {
      id: data.rows.item(0).id,
      first_name: data.rows.item(0).first_name,
      surname: data.rows.item(0).surname,
      gender: data.rows.item(0).gender,
      dob: data.rows.item(0).dob
    }
  });
}

And on patient.page.ts I have the following to determine if the page should be in new-patient mode, or edit-patient mode:

ngOnInit() {
  this.route.paramMap.subscribe(params => {
    let patientId = params.get('id');

    // patientId will be 0 for new patients passed from db service
    if (patientId != 0) {
      console.log('patient.page.ts:ngOnInit:patient found');
      this.db.getPatientById(patientId).then(data => {
        this.patient = data;
      });
    }
    else {
      console.log('patient.page.ts:ngOnInit:patient not found, creating new patient');
      this.patient =
      {
        id: 0,
        first_name: '',
        surname: '',
        gender: '',
        dob: ''
      }
    }
  });
}

This creates a new patient if the id was not set when opening the page. Any help much appreciated.

You should be good to go after adding

this.patient =new Patient
(
id: 0,
first_name: ‘’,
surname: ‘’,
gender: ‘’,
dob: ‘’
)

I tried that and got the following errors:

src/app/pages/patient/patient.page.ts(37,13): error TS1005: ',' expected.
src/app/pages/patient/patient.page.ts(38,21): error TS1005: ',' expected.
src/app/pages/patient/patient.page.ts(39,18): error TS1005: ',' expected.
src/app/pages/patient/patient.page.ts(40,17): error TS1005: ',' expected.
src/app/pages/patient/patient.page.ts(41,14): error TS1005: ',' expected.

Here’s what I changed (lines 37 to 41 start at “id: 0”):

ngOnInit() {
this.route.paramMap.subscribe(params => {
  // let patientId = params.get('id');

  let patientId = 1;

  // patientId will be 0 for new patients passed from db service
  if (patientId != 0) {
    console.log('patient.page.ts:ngOnInit:patient found');
    this.db.getPatientById(patientId).then(data => {
      this.patient = data;

      console.log('patient.page.ts:ngOnInit:id:' + this.patient.id);
      console.log('patient.page.ts:ngOnInit:first_name:' + this.patient.first_name);
    });
  }
  else {
    console.log('patient.page.ts:ngOnInit:patient not found, creating new patient');
    this.patient = new Patient
    (
      id: 0,
      first_name: '',
      surname: '',
      gender: '',
      dob: ''
    );
  }

I also noticed the following error when my original code is executed:

ERROR TypeError: Cannot read property 'executeSql' of undefined
at DatabaseService.push../src/app/services/database.service.ts.DatabaseService.getPatientById (database.service.ts:170)

Lines 169 and 170 look like this:

console.log('patient.page.ts:getPatientById:patient id received:' + id);
return this.database.executeSql('SELECT * FROM patient WHERE id = ?', [id]).then(data => {

The console debug window shows this when the app is run:

patient.page.ts:ngOnInit:patient id received:1

So I can at least confirm that the getPatientById method is receiving an id value, but I don’t understand the reported error.

It looks like the database object has not been initialized based upon the error.

Listed before that error, the console output displays this:

OPEN database: test.db
OPEN database: test.db - OK

Which I assume means that the db is ready for use before the getPatientById is called?

Is it a bad idea to have the getPatientById method call in the ngOnInit() method? What page event would be more suited?

No. It’s a bad idea for anything outside the DatabaseService to know or care about implementation details like readiness of the underlying database. A quick look at the tutorial link you provided suggests that the DatabaseService in it is properly handling initialization, so if you’re following that, all client code should be protected from such concerns.

As for your other issue with the broken syntax trying to create the blank patient, you have to decide where you want the responsibility to lie. I would put it on the controller code, which means you don’t have to modify your template, but you do have to take away the fact that patient could be undefined, with something like:

patient = new BehaviorSubject<Patient>({} as Patient);