0

I started with four components:

  • UserListComponent
  • UserSearchComponent
  • GroupListComponent
  • GroupSearchComponent

Both list components reference their corresponding search component via a ViewChild decorated property. For example, the UserListComponent has a property defined like:

@ViewChild(UserSearchComponent)
userSearch: UserSearchComponent;

The two list components and search components were so similar with each other, I started looking into how to have components extend base classes so that I Did not Repeat Myself. I started by creating a base class for the search components with the following declaration:

@Component({
  selector: 'td-search',
  template: ''
})
export class SearchComponent<T> {
  ...
}

Once I extended the two search components, my ViewChild references, in both cases, ended up returning undefined. For example, here is the UserSearchComponent's declaration after introducing the base class:

export class UserSearchComponent extends SearchComponent<UserSearch> {

UserSearch is just a class that wraps available search parameters as an object/payload to send off to the server.

So the ViewChild properties work in both cases as long as I don't have a base class for the two search components. But as soon as I introduce a base class, I can't seem to get a ViewChild reference of the types of the two search components.

The error I get looks like this: enter image description here

...and I'm just trying to set a property on the search component once the results come back in the list component by calling this method:

private resetSearch() {
  this.loading = false;
  this.userSearch.disabled = false;
}

Question:

Can I use base classes with components I intend to use as ViewChild references?

Update:

I made the realization, too, that the ViewChild is NOT undefined at first... in ngOnInit of the UserListComponent, I am subscribing to a searches property of the UserSearchComponent (of type EventEmitter<UserSearch>). This successfully finds the UserSearchComponent and I confirmed this by logging out the whole object right before making the subscription call:

console.log(this.userSearch);
this.userSearch.searches.subscribe((search: UserSearch) => {
  this.loading = true;
  const params = new UserSearchQueryParams();
  params.Login = search.login;
  params.Username = search.user;
  params.EnabledOnly = search.enabled;
  this.users$ = this._users.getUsers(params).pipe(
    catchError(this.handleError),
    finalize(this.resetSearch)
  );
});

In the finalize operator of the call to getUsers observable, I call resetSearch which is where this.userSearch is returning undefined. So before I do the search, the search component child reference works, but after the search takes place, the list component's child reference to the search component doesn't work...

Jake Smith
  • 2,332
  • 1
  • 30
  • 68
  • is there a `@ViewChild` in the base class? – joh04667 Oct 01 '18 at 18:33
  • There is not. The base class just gives the two search components some shared functionality but has no child components it needs to reference – Jake Smith Oct 01 '18 at 18:35
  • Try removing the selector of the base class (assuming that each derived class has its own selector). – ConnorsFan Oct 01 '18 at 18:38
  • Cool. Then, is there a `userSeach` property defined in the base class? Also, it's a lot to ask, but if you could set up a StackBlitz with an example of this, it would be really helpful. – joh04667 Oct 01 '18 at 18:41
  • @ConnorsFan thanks for the suggestion! I tried it, but see the same behavior still :( – Jake Smith Oct 01 '18 at 18:51
  • @joh04667, the `userSearch` property is the `ViewChild` reference in the list component. The base class does not have a property with this name – Jake Smith Oct 01 '18 at 18:51
  • Possible duplicate of [How to access the correct \`this\` inside a callback?](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback) – ConnorsFan Oct 01 '18 at 19:01

1 Answers1

0

BUMMER, this ended up being way less interesting than I was hoping for. In my subscriptions to the searching requests from the user, I was using the finalize operator on the observable that is the call to getUsers, and was attempting to use a method group like I can in C#:

this.userSearch.searches.subscribe((search: UserSearch) => {
  this.loading = true;
  const params = new UserSearchQueryParams();
  params.Login = search.login;
  params.UserName = search.user;
  params.EnabledOnly = search.enabled;
  this.users$ = this._users.getUsers(params).pipe(
    catchError(this.handleError),
    finalize(this.resetSearch)
  );
});

If I change the usage of the finalize operator to not include a method group, like so:

...
    finalize(() => this.resetSearch())
...

... then my this.userSearch does not return undefined in the body of resetSearch. I've run into the issue of trying to use method groups in typescript before. Sometimes they work, sometimes they don't, but this is a case of when they don't and I should just stop trying to use them I think...

Jake Smith
  • 2,332
  • 1
  • 30
  • 68