Akvelon | Implementing Nested Custom Controls in Angular 5
Implementation, modularization, and testing of nested custom controls for using with Reactive Forms and Template-Driven Forms
implementing custom controls in Angular 5, Angular 5, code, coding, nested custom controls, Reactive Forms, Template-driven forms
20346
post-template-default,single,single-post,postid-20346,single-format-standard,ajax_fade,page_not_loaded,,qode-theme-ver-8.0,wpb-js-composer js-comp-ver-4.9.2,vc_responsive
 

06 Apr Implementing Nested Custom Controls in Angular 5

Implementation, modularization, and testing of nested custom controls for using with Reactive Forms and Template-Driven Forms

This article was written by Software Development Engineer Vadim Korobeinikov and was originally published on Medium

Motivation

Very often we embed third-party component libraries in Angular projects. But no matter how cool the library is, sometimes one needs to modify library components UI while keeping the component and added styling separated, to enable easy component upgrade and solution management. Here we present a way of overriding isolated component styles, e.g making style changes without direct modification to third-party component. Moreover, we will isolate customized components by wrapping them to modules. Modularity is one of the greatest features of Angular, allowing us to keep the project maintainable, clean and extensible.

Problem Statement

On one of the projects here in Akvelon, we applied Project Clarity components library on the front-end side. All looked good. but the appearance of some components did not match the requirements. These were inputs and selectboxes which should have borders on all sides, have same sizes and so on. Besides, HTML forms contain many controls supplemented by the labels which increase code duplication.

                                                                           Design of components provided by library
                                                                         Components according to the requirements

Requirements

At design time we highlighted the features that the custom components should have:

  • Work with Reactive Forms and Template-Driven Forms.
  • Validate user input.
  • Support two-way data binding with ngModel as we have stand-alone components outside of the forms.
  • Allow customization by applying styles per emerging requirements.
  • Ability to be marked as required when necessary (appending asterisk and make elements red or something like that).

In order to meet the requirements, we came to the following solution.

Solution

The most reliable approach is to create separate components for each element:

  • custom-input
  • custom-selectbox
  • custom-labeled
  • custom-labeled-input
  • custom-labeled-selectbox

We detected that inputs and selectboxes are the most widely used controls in our project. That’s why we created separate components for them. custom-labeled appends label to the pushed component, it is kind of a base part. custom-labeled-* components intended to unite custom-labeledcomponent and corresponding custom-* component.

As a benefit keeping these building blocks as separate components,  the amount of HTML code in template files decreased significantly. See the difference in the following code snippets.

 

                                                                                                                                 Using custom components

 

                                                                                                                             Without custom components

Additional Improvements

It is a good idea to wrap such things in their own modules, which will be also covered below. Additionally, we will take a look at the unit tests of components, especially with two-way data binding.

Implementation

In this article, implementation steps will be performed only for input related components. Here we are going to implement InputComponent which will keep customized input control. The next step is creating base LabeledComponent. It will keep customized label and attach it to the child component. One more component should connect the two mentioned components, so we will create LabeledInputComponent. Finally, we will add them to the special components module and cover by unit tests. You can explore the code which also includes selectboxes related stuff on GitHub.

Create Input Component

According to our strategy, we will create a custom input component with the following properties and event bindings. We will allow the user to change only the narrow set of properties, namely value, type, id, and placeholder.

 

Connect Angular forms API with DOM element

To tell Angular how to access the value of the custom component, we have to provide the implementation of ControlValueAccessor interface.

The interface includes three method declarations:

  • writeValue called to write data from the model to the view
  • registerOnChange registers reaction on changing in the UI
  • registerOnTouched registers reaction on receiving a blur event (is emitted when an element has lost focus)
  • setDisabledState called on Disabled status changes

Let’s implement them.

 

Provide ControlValueAccessor for component

Now we have to tell the component to register itself as NG_VALUE_ACCESSOR provider. To implement it we have to include the corresponding provider into the component’s configuration metadata.

 

After the change, the value of custom-input will be visible, for example, via the {{ }} syntax. Now we are able to change the style of the custom component and use it throughout the project.

Create LabeledComponent base

As mentioned before, this is a parent component containing child components using ng-content. Here, the required class simply appends asterisk on the label.

 

Create LabeledInput Component

Now we are ready to create the labeled component, combining LabeledComponent and InputComponent. It has to implement ControlValueAccessor and register itself as a provider to support two-way data binding.

                                                                                              

Create separate module for custom components

Modules in Angular applications help to separate responsibilities of project parts, make project maintainable and so on. Our custom components are good candidates to be pushed into their own module. They are responsible for representing data. Let’s create a new module using angular cli command: ng g module custom-controlsThere we will declare necessary components and export just those we want to share.

 

Add unit tests

Unit testing is a valuable aspect in the software development lifecycle. We have to be sure that all created components work as expected. Here we are checking correctness by bounding data to a host component, such as InputComponent which is tested below. Inside a test we created new components which hosts only component we want to test. Tests for labeled components will look pretty much the same. You can find detailed description of component inside a test host testing approach on Angular docs.

 

Conclusion

We implemented approach which makes components customizable and easy to use. Through components nesting we can easily change styling of any UI element type according to new requirements only in one place thus keeping uniformity. Addition of unit tests and wrapping components in a separate module makes it a good starting point for making your own components library and using it in multiple projects.

You can find the source code on GitHub repository or check it right away on Stackblitz.

Vladim Korobeinikov Akvelon

Vadim Korobeinikov is a Software Development Engineer at Akvelon. He has extensive experience in full-cycle development of multi-platform (mobile, web, desktop) business applications based on multiple stacks of technologies (C#/.NET, Node.js, JavaScript and others).


More Insights

Machine Learning Platform for Data Analysis



Nail Shakirov, a Project Manager at Akvelon, has written an article on one of Akvelon’s Machine Learning projects. This article was published in Medium and Towards Data Science, excellent read!

 

Akvelon Ranks Top 1% In First Round of Google Programming Competition, Qualifies for Final Round

Team Axis Violation Google Akvelon

Akvelon team places in top 1% at Google’s programming challenge competition Hash Code 2018, qualifying to compete in Final Round in Dublin

 

Entering the World of Machine Learning and AI with MOOCs


Online Learning AI and ML

An engineer’s education doesn’t stop of college. There are so many resources to learn more skills, such as Machine Learning and AI technology, and one is to take online courses using Massive Open Online Courses.

 

No Comments

Sorry, the comment form is closed at this time.

Akvelon

Akvelon

Akvelon provides software engineering solutions to businesses of all sizes. From AI to Cloud, our tech can help you. Contact Us