angularngx-datatable

Angular - How to resolve "Property does not exist on type 'never'" in @tusharghoshbd/ngx-datatable Advanced Search


In my Angular-13 project I am trying to implement Advance Search in @tusharghoshbd/ngx-datatable

I have this code:

interface:

export interface Merchant {
  id?: number;
  merchant_name?: string;
  account_number?: string;
  merchant_status?: number;
  created_date?: string;
}

service:

  import { Merchant} from 'src/app/models/merchants.model';

  getAllMerchants(): Observable<Merchant[]> {
    return this.http.get<Merchant[]>(this.baseUrl + 'merchants');
  }

component.ts:

import { MerchantService } from 'src/app/services/merchant.service';
import { Merchant} from 'src/app/models/merchants.model';

export class MerchantsComponent implements OnInit {
  @ViewChild('idTpl', { static: true }) idTpl!: TemplateRef<any>;
  allMerchantList: any[] = [];
  data = [];
  dataBK = this.allMerchantList;
  options = {};
  columns: any = {};    
  constructor(
    private merchantService: MerchantService,
    ) { }

  ngOnInit(): void {
    this.loadDatatable();
    this.loadAllMerchants();
  }

  loadDatatable(){
    this.columns = [
      {
        key: 'id',
        title: '<div class="blue"><i class="fa fa-id-card-o"></i> SN.</div>',
        width: 60,
        sorting: true,
        cellTemplate: this.idTpl,
      },
      {
        key: 'merchant_name',
        title: '<div class="blue"><i class="fa fa-user"></i> Merchant</div>',
        width: 100,
        sorting: true,
      },
      {
        key: 'account_number',
        title: '<div class="blue"><i class="fa fa-envelope"></i> Account No.</div>',
        width: 100,
        sorting: true
      }
    ];
  }

  loadAllMerchants(){
    this.merchantService.getAllMerchants().subscribe({
      next: (res: any) => {
        this.allMerchantList = res.result;
        this.dataBK = this.allMerchantList;
      }
    })
  }

  onMerchantNameSearch(value: any)
  {
    this.data = this.dataBK.filter(row => row.merchant_name.toLowerCase().indexOf(value) > -1);
  }

  onAccountNumberSearch(value: any)
  {
    this.data = this.dataBK.filter(row => row.account_number.toLowerCase().indexOf(value) > -1);
  }
}

component.html:

<div class="col-sm-4 col-xs-6 col-6 ">
  <div class="form-group">
    <label for="merchant_Name">Merchant Name:</label>
    <input type="text" autocomplete="off" class="form-control" (input)="onMerchantNameSearch($event.target.value)" id="merchant_Name" placeholder="Merchant Name"/>
  </div>
</div>
<div class="col-sm-4 col-xs-6 col-6 ">
  <div class="form-group">
    <label for="account_number">Account No.</label>
    <input type="text" autocomplete="off" class="form-control" (input)="onMerchantNameSearch($event.target.value)" id="account_number" placeholder="Account Number"/>
  </div>
</div>

  <ngx-datatable tableClass="table table-striped table-bordered table-hover" [data]="allMerchantList" [columns]="columns" [options]="options">
    <ngx-caption>
      </div>
    </ngx-caption>

    <ng-template #addressTpl let-row let-rowIndex="rowIndex" let-columnValue="columnValue">

    </ng-template>
    <ng-template #idTpl let-rowIndex="rowIndex" let-row="row">
      {{rowIndex+1}}
    </ng-template>

  </ngx-datatable>

console.log(res);

gives:

"result":[
    {
        "id": 1,
        "merchant_name": "Appiah",
        "account_number": "332222",
        "merchant_status": 1,
        "created_date": "2022-01-24T12:51:08.19",
    },
    {
        "id": 2,
        "merchant_name": "Kwesi",
        "account_number": "554444",
        "merchant_status": 1,
        "created_date": "2022-01-25T16:43:41.873",
    },
    {
        "id": 3,
        "merchant_name": "fggffgfgfg",
        "account_number": "455654",
        "merchant_status": 1,
        "created_date": "2022-01-25T16:46:20.77",
    }
]

and

console.log(this.allMerchantList);

gives:

[
    {
        "id": 1,
        "merchant_name": "Appiah",
        "account_number": "332222",
        "merchant_status": 1,
        "created_date": "2022-01-24T12:51:08.19",
    },
    {
        "id": 2,
        "merchant_name": "Kwesi",
        "account_number": "554444",
        "merchant_status": 1,
        "created_date": "2022-01-25T16:43:41.873",
    },
    {
        "id": 3,
        "merchant_name": "fggffgfgfg",
        "account_number": "455654",
        "merchant_status": 1,
        "created_date": "2022-01-25T16:46:20.77",
    }
]

As I enter values on the input fields in the Advance Search, I expect the result in the @tusharghoshbd/ngx-datatable.

But before I even do that at all, I got this error in the component:

error TS2339: Property 'merchant_name' does not exist on type 'never'.

192 this.data = this.dataBK.filter(row => row.merchant_name.toLowerCase().indexOf(value) > -1);

How do I resolve this?

Thanks


Solution

  • Maybe don't use the dot-notation to get an property of an anonymous object. It could be, that the compiler sees this case wrong.

    onMerchantNameSearch(value: any)
    {
        this.data = this.dataBK.filter(row => 
            row['merchant_name'].toLowerCase().indexOf(value) > -1);
    }
    
    onAccountNumberSearch(value: any)
    {
        this.data = this.dataBK.filter(row => 
            row['account_number'].toLowerCase().indexOf(value) > -1);
    }
    

    If you don't want to run into errors like that (and it seem to be a little problem of the TypeScript convert), then you could disable "strictNullChecks" in your angular.json file. Then the type "never" wouldn't be existent.

    Your MerchantService is probably not correct. HttpClient.get directly returns the body, except when you are adding the options parameter and set the "observe"-propery. So try changing the subscription as follows:

    this.merchantService.getAllMerchants().subscribe((res: any) => {
        this.allMerchantList = res;
        this.dataBK = this.allMerchantList;
    })
    

    Also have a look into my example: https://stackblitz.com/edit/angular-rrdq9z?file=src/app/app.component.ts