Accessing a Child Component’s Public Scope in Angular
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, ngModel
. Additionally, 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.
Published on Web Code Geeks with permission by Jeroen Savat, partner at our WCG program. See the original article here: Accessing a Child Component’s Public Scope in Angular Opinions expressed by Web Code Geeks contributors are their own. |