With our dynamic tabs we also want to give our users the possibility to close them again. As such we also need to account for destroying our dynamically created components. In this lesson we will learn how the ViewContainerRef
can help us with that.
Instructor: [00:00] Here we have a pretty complete implementation of such a dynamic tab component. As you can see here, we have the tabs. We have the single tab here, which is a static one. Then we have below defined a template which, whenever we click some action -- for instance that "add new person" -- we dynamically instantiate new such tabs and we pass along that template, which we have defined here.
[00:22] For instance, if you take a look here, and that list, basically which renders this part here, as well as the button, we have different kind of events, which we hook into our component. Then, inside there, we simply invoked the open-tab method on our tabs component, which then basically takes some parameters, which is the title, which should be displayed on top here.
[00:42] It also takes along the template and eventual data that gets passed on, for instance, an added person we pass on, the person that is being edited. In that case, internal, then the tab component takes care, in that open tab, to dynamically instantiate the tab component to reference all the data, and then basically to select the tab. As a result, you can see how that gets instantiated dynamically here.
[01:07] What we would like to focus in this lesson is to provide some further functionalities to cancel such tabs, so to close it again, for instance, whenever we click that Save button, or via an icon, which we can display up here. During that phase, we need to also take care to properly destroy those dynamic components here, in order to avoid memory leaks.
[01:27] Let's see how we can implement such a scenario. First of all, let's go into the tab component and let's add in our input property here, which is called isCloseable, which is false initially. This will mark where our tab can actually be closed or whether it's a permanent tab.
[01:44] Next, we need to go into our tab component and we want to adjust our header section here, such that we can render some kind of icon or something the user can click on to close the tab again. For that purpose, I go directly into the dynamic part here and say span.
[02:02] We obviously want to display this only when the tab is actually closeable. Whenever the user clicks on that, we want to invoke some function, which is called closeTab, and we pass along the tab, as well.
[02:18] Obviously, we need to create this function. Let's jump below here and enter here this closeTab. We get here a tab component as the parameter. Given the tab instance here, we need to also find the corresponding match in our array in order to remove it from there. Let's simply iterate over the dynamic tabs array and fetch it out.
[02:46] Now these references match. We know that we found our tab, so what we can do, first of all, we can remove it. Let's use here splice. Now we have removed the tab from our array, such that it doesn't remain inside there.
[03:00] The next time, we then need to make sure we destroy our component. For that purpose, we again need to get a reference to our containerRef. The viewContainerRef has a convenient method on it, which is remove. Then you can provide it an index, where you want to remove, basically, the dynamic component.
[03:20] Since we iterate over our array and we know that we have added our component on that array at the same time when we have added the to.viewContainerRef, we can rely on the same index number. We can simply pass in i.
[03:31] Then, as a final step, just to make it look a bit prettier, let's select the first tab again. Given that we have found our tab, we can simply break out of this loop here to optimize a bit the performance.
[03:44] What we have missed here is to actually also assign an isCloseable property onto our tabs, such that it can be passed from outside. We set isCloseable to isCloseable, and there's a parameter we need to add here on top. We can even make it an optional parameter, so, in that case, the user doesn't have to specify it always.
[04:03] Now let's jump back to our app-component, and then we can say, like on the editPerson, we want it to be closeable, so you can always abort that action, as well as, on the editing of a new person, we want to be that closeable again. With that, whenever now I click add person, I can click here the X again, and it closes, and, similarly, also for the editing here.
[04:24] What's probably missing is whenever we click here, say if we would also like to have our tabs being closed, we could do that by simply going here to [inaudible] submit. At the very end, we say this.tabscomponent.closetab.
[04:35] Since we are not sure which tab is currently open, we could add something like closeActiveTab, which is something we have to create. We go into our tabs component, at the very end, and we add here the closeActiveTab function. That function will simply grab the active tab, which we can do by using the this.dynamictabs.filter, and we verify all the tabs where that tab is active.
[05:07] Whenever we have found such tab, we simply invoke the close tab function, which we already have here, from those tabs which we have found. From the first one, which I have found, and now, if we edit a person -- for instance I live right here, not Juri, but Thomas -- we say save, you can see it has being edited.
[05:23] You can also add new people. Obviously, since this is a tab component, we can add new people. We can edit people at the same time, so we can change it here and change it here, as well.
[05:34] As you can see, now we have a fully functional tab component, where we have just some hard-coded tabs, which is the first one, and then we have some dynamic tabs, which open up based on the user interaction.