Override Component UI with an Angular TemplateRef

Isaac Mann
InstructorIsaac Mann
Share this video with your friends

Social Share Links

Send Tweet

What if we want to use some of the state in the toggle component inside of the customized view we’re providing. Content components don’t have an easy way of accomplishing that. However, TemplateRefs were specifically designed for this purpose. TemplateRefs serve the same function as React’s Render Prop pattern.

Instructor: [00:00] This compound toggle component gives you three child components that let you interact with the state of the toggle. This toggle button lets you toggle the value on or off.

[00:10] The toggle-on component displays something when the toggle is on. The toggle-off component displays something when the toggle is off. These three child components fully cover all the possible values of the toggle.

[00:22] Say we had a component with state that was a bit more complicated. What we'd really want is for a toggle component to just give us the state that's inside of it and let us fill in the details of how to display that.

[00:34] The way we'll do that is using the ng-template tag. You can explicitly specify which part of the state you're interested in and then use that state inside of your template.

[00:45] This template isn't wired up at all. Let's go do that. First off, we can get rid of these child components. You see our toggle module gets a lot simpler. We'll need to change this toggle directive back into a component.

[01:03] Let's set up the TemplateRef. We'll get a reference to the TemplateRef using ContentChild. We'll call it layout template.

[01:11] Let's define the template for this component. In order to use the TemplateRef, we need an element to drop it on, but we don't need a real HTML element. We'll use the ng-container placeholder.

[01:24] To instantiate the TemplateRef, we'll use the ngTemplateOutlet structural directive. We'll tell it to use the layout template. We also want to specify a context, which is how we can pass in the state of this toggle component.

[01:38] If we go back to the app component, you see we're passing in the on state. The value is false. We're displaying off here. We'd also like to be able to update the state.

[01:49] We'll add in a switch component and then use the click event to trigger some function that will update the toggle state for us. We need the TemplateRef to provide us with that toggle function that will update the state when we call it.

[02:01] We need to hook that up in the toggle component. All we need to do is add to the context object a toggle property that references a toggle function. We'll define that toggle function in the component.

[02:13] We'll define the toggle function using an arrow function to automatically bind the this context to the toggle component. We can do this.setOnState with not this.on.

[02:26] We need to update this output event to be toggled so the name doesn't conflict with this function here. When we click the switch, it changes the state.

[02:35] Let's compare the before and after here. There's just one toggle component. We've gotten rid of the child components. The app component simply uses the state that's passed in and uses a function that's provided here to change that state.

[02:51] The parent component is both more flexible, because we're dealing with the raw state, and simpler, because we don't need to learn a new set of child components for each new compound component that we use.

[03:02] There are a few items to tidy up with this implementation. We should change this div tag to a toggle tag, so that people don't expect it to behave like a directive, since it's really a component.

[03:12] This red squiggle here is actually a false negative. It doesn't really hurt anything, but if you really want to get rid of it, you can work around doing something like this.

[03:22] Pass in a functions object that has functions.toggle defined on it and then hook it up in your toggle component. Instead of putting toggle here, you rename it to functions.

[03:33] Make it an object that has toggle defined on it. If you go back to the TemplateRef, it no longer has a validation error. The component works just as it did before.