In this blog series, we’ll look at the two primary methods of creating a reusable custom component in Angular 2: class inheritance and aggregation. We’ll look at the pros and cons of each method and dive into their implementations.
Your Angular 2 application may require specialized UI elements that deal with specific parts of your application domain. For example, you may need a grid that operates as a checklist, or you may need a grid with a predefined set of columns to represent order items. Of course, you can always take a WjFlexGrid component and set it up anywhere you need to. However, what if you need a particular configuration in multiple places throughout your application? If you decide to rework the UI, you will need to propagate the changes to all instances of the control, and you will get all the maintenance and QA troubles inherent in duplicated code. The best solution is to create a custom Angular 2 component that implements all necessary UI and behavior specifics, and reuse it whenever you need. For example, you can take the WjFlexGrid component as a base, apply necessary customizations, and wrap it in the single component class that will function as a self-sufficient reusable application unit. In the world of TypeScript and Angular 2, two key techniques can be used to create new classes from existing ones: class inheritance and aggregation. Let’s look at the pros and cons of each.
When we inherit from a base class, we inherit all its API and functionality. With the API, this may be good or bad. If you need a custom grid class that uses all of WjFlexGrid’s possible settings, but only adds a bit of specific functionality (like adding an InputDate control to edit date cells), then it’s good. It’s a straightforward use of WjFlexGrid, and changing other properties isn’t likely to break the new control.
For more complex components, though, inheritance is less desirable. If you want to create the Order Items grid I mentioned, where there’s a predefined set of columns and only one property that could be safely changed (itemsSource), you run the risk of another developer unintentionally changing an inherited property. That could break the component’s functionality. In this case, the aggregation is the right way to go.
In the latter case, you could define a component class that creates a WjFlexGrid instance internally, most likely by adding the class to its template. Since the new component initially has no exposed properties or events, you can choose to add only those that are relevant to its functionality. Some will probably pass through their values to the internal WjFlexGrid instance. Another benefit to aggregation is that you can create a more complex UI than the base class offers. For example, you could create a component that represents a grid with the filter input element above it, thus introducing a reusable “grid with filter” version. Let’s look at a sample that illustrates both approaches.
This sample implements the same grid using inheritance and aggregation.
In this sample, we’re building a grid with checklist capabilities. Checklist requirements include:
The radio button and checkbox options are controlled by the component’s selectionType: Single|Multiple enum property. Here’s how the grid looks in the single row selection mode: Single row selection mode The custom grid also supports dynamic inline row editing:
Because of the inline editing approach, standard grid selection functionality is disabled. In addition, selected rows are marked in the Select column, and this state is reflected in the items source’s active boolean property to which the column is bound. The component also offers the isEditable boolean property, which allows us to disable all cell editing. Here’s a look at disabled editing and multi-row selection: Disabled editing and multi-row selection If editing is disabled, all input elements in grid cells become disabled. Note: even if editing is disabled, the row selection functionality continues to work. In the next blog we’ll go deeper into the process of creating an InheritedGrid component.