Angular 6 - Unable to run external functions inside a particular function
Asked Answered
H

2

8

I'm using ng-select for angular 6.

This is the HTML side of it:

        <ng-select [(ngModel)]="client.categoryId"
                   class="form-control"
                   [ngClass]="{'is-invalid':clientCategoryId.errors && clientCategoryId.touched}"
                   #clientCategoryId="ngModel"
                   name="categoryId"
                   [addTag]="addTagNow"
                   required>
          <ng-option *ngFor="let cat of cats" [value]="cat.id">{{cat.title}}</ng-option>
        </ng-select>

And this is the typescript:

nCategory: Category = {
  title: ''
};

constructor(public afs: AngularFirestore) {
  this.categoriesCollection = this.afs.collection('categories', ref => ref.orderBy('title', 'asc'));
}

addTagNow(name) {
  this.nCategory.title = name;
  this.categoriesCollection.add(this.nCategory);
}

This is the error:

NgSelectComponent.html:91 ERROR TypeError: Cannot set property 'title' of undefined at NgSelectComponent.push../src/app/components/edit-client/edit-client.component.ts.EditClientComponent.addTagNow [as addTag] (edit-client.component.ts:169)

If I run the code outside of AddTagNow function it works perfectly fine.

How can I execute that code?

Hussy answered 1/8, 2018 at 20:36 Comment(0)
P
13

You are passing a reference to an object method, but the value of this is not being set. So you need to bind(this) to the function reference.

public addTagNowRef: (name)=>void;

constructor(public afs: AngularFirestore) {
  this.categoriesCollection = this.afs.collection('categories', ref => ref.orderBy('title', 'asc'));
  this.addTagNowRef = this.addTagNow.bind(this);
}

Then use that property in the template.

<ng-select [(ngModel)]="client.categoryId"
           class="form-control"
           [ngClass]="{'is-invalid':clientCategoryId.errors && clientCategoryId.touched}"
           #clientCategoryId="ngModel"
           name="categoryId"
           [addTag]="addTagNowRef"
           required>
  <ng-option *ngFor="let cat of cats" [value]="cat.id">{{cat.title}}</ng-option>
</ng-select>

Alternatively, you can use an arrow function to forward the call to the method.

public addTagNowRef: (name)=>void;

constructor(public afs: AngularFirestore) {
  this.categoriesCollection = this.afs.collection('categories', ref => ref.orderBy('title', 'asc'));
  this.addTagNowRef = (name) => this.addTagNow(name);
}

The point here is that this must reference the component.

Pigeonhole answered 1/8, 2018 at 20:50 Comment(2)
Thank you so much I would never, ever, ever, figure this out.Hussy
@Omar it's a function on the component. See the OPs example code.Pigeonhole
P
2

I solved this problem by using .bind(this) :

<ng-select [(ngModel)]="client.categoryId"
           class="form-control"
           [ngClass]="{'is-invalid':clientCategoryId.errors && clientCategoryId.touched}"
           #clientCategoryId="ngModel"
           name="categoryId"
           [addTag]="addTagNow.bind(this)"
           required>
  <ng-option *ngFor="let cat of cats" [value]="cat.id">{{cat.title}}</ng-option>
</ng-select>
Parody answered 18/2, 2021 at 13:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.