• Jeroen Savat

  • Frontend Software Engineer

When you can't touch the codebase.

I was asked to create an autocomplete component that would do some filtering on a list and include a “clear” button that could reset this filter. Not a problem, if it wasn’t for the fact that it was this Angular newbie’s first ever Angular story in an Angular 4 project. #Angular

In a React-Redux setup (which is what I’m used to), managing values is a matter of working with Redux. Resetting a value would mean dispatching an action that empties a certain part of your application state; in this case, the value of the allLabels input:

<search-filter
    id="allLabels"
    name="allLabels"
    flyoutSize="full"
    flyoutAlign="right"
    label="Find stuff"
    labelDeselect="Clear stuff"
    labelResults="Found stuff"
    labelNoResults="Couldn't find stuff!"
    placeholder="Look for stuff"
    inputDelay="0"
    [choices]="stuff"
    [showAllByDefault]="true"
    [remote]="true"
    (search)="findStuff($event)"
><search-filter>

The API of this component did not seem to expose a way to modify the value like you would with a normal input using, for example, ngModelAdditionally, in our case, this is a third party component, which means we cannot alter its codebase.

When looking at the component’s internal code, it’s fairly easy to figure out that the public “reset” method would reset the value. After attempting this, however, it didn’t seem possible (to me) to access this method.

this.categoryFilter.value = ‘’; // nopetynope
this.categoryFilter.reset(); // nopes

A colleague who is wise in the ways of Angular presented the solution to me:
“Just use a viewchild decorator.”

Looking at the documentation, though, I was none the wiser. What is it? What does it do? How do I use it? #clueless

The viewchild decorator

Thankfully, my colleague (who soothed my ego by saying the documentation “might not be very clear”) explained it to me. Allow me to explain!

First, there’s the matter of referencing the component:

<search-filter
   #categoryFilter
   id="status"
… />

Then, we “couple” this reference with a viewchild decorator. (Not coming from an OOP background, the concept of decorators was also new to me, but it’s fairly easy to understand when you read up about it.)

@ViewChild('categoryFilter') categoryFilter: SearchFilterComponent;

This allows us to reference any “public” methods or properties of our categoryFilter component - for example, the “clear” method!

this.categoryFilter.clear(); // does the clearing!

 

So, putting it all together it looks like this:

<searchFilter.component.html>
<search-filter
   #categoryFilter
   id="status" />
...
<button title="clear categories" (click)="clearCategories()">clear</button>
...
<searchFilter.component.ts>
@Component({
    selector: 'search-filter',
    templateUrl: './searchFilter.component.html',
    styleUrls: ['./searchFilter.component.css']
})
export class SearchFilter implements OnInit {
    @ViewChild('categoryFilter') categoryFilter: SearchFilterComponent;
...
clearCategories(): void {
    this.categoryFilter.clear(); // does the clearing!
}
...
}


The viewchild decorator is a useful pattern in cases where you need to reference (and call) a child component(‘s methods), but can’t alter the codebase for whatever reason. Do you know of an alternative, or even a better way? Feel free to let us know.