Telerik blogs

Today, we will learn how to extend and customize Kendo UI components in our app using Angular directives. Directives help us with replicating configuration and behavior without adding extra components, and they have clear, scalable, semantic and transparent code.

The Scenario

We want our developers to use the Angular Calendar from Kendo UI for Angular in the application but with the same configuration by default. For example:

  • All Calendars start with the current date selected.
  • Hide the Calendar Navigation.

Our solutions need to show the kendo-calendar, but by default show the current day and hide the navigation. We have two approaches for solving it—using either:

  • A component wrapper
  • Angular directives

Component Wrapper

The component wrapper works as a bridge between the Kendo UI Calendar component and our app. The app uses the inputs to set the properties for the kendo-calendar.

First, create the CompanyCalendar component using the angular/cli

ng g component companycalendar

Next, add two @Input properties showNavigation and currentDate.

export class CompanyCalendarComponent  {
  @Input() showNavigation =false;
  @Input() currentDate: Date = new Date();
}

In the template, assign the showNavigation input to navigation and currentDate to value in the <kendo-calendar>.

<kendo-calendar type="infinite" [value]="currentDate" [navigation]="showNavigation">
</kendo-calendar>

Next, the app uses the CompanyCalendarComponent, and the developers use the input properties to alter the default Calendar behavior because the initial value for showNavigation is false.

<div>
<h3>Subscribe</h3>
<app-company-calendar></app-company-calendar>
</div>

<div>
  <h3>Purchase</h3>
  <app-company-calendar [showNavigation]="true"></app-company-calendar>
</div>

<div>
  <h3>Birthday</h3>
  <app-company-calendar></app-company-calendar>
</div>

Perfect—it works as expected. All calendars look like Kendo UI with the same behavior; also, the app-company-calendar allows us to hide and show the navigation.

The Hidden Cost

Our first approach works, but it has a list of side effects for our team:

  • It creates an extra layer between Kendo UI Calendar.
  • The Wrapper limits the power of the Kendo UI Calendar.
  • We get an unexpected behavior when missing properties.
  • We need to document every single input property.
  • We don’t know if some property is required or not.
  • New joiners need to learn about the wrapper component.

It is too costly only for customizing our UI. Let’s try to take another approach.

Angular Directives

Angular directives allow changing the component behavior in the template without adding an extra component. We’re going to create two directives CompanyCalendar and CurrentDate for each use case.

The directive companycalendar works to configure the calendar as the company wants:

ng g d directives/companycalendar
CREATE src/app/directives/companycalendar.directive.spec.ts (268 bytes)
CREATE src/app/directives/companycalendar.directive.ts (163 bytes)
UPDATE src/app/app.module.ts (869 bytes)

Angular directives use selectors to find element names to trigger the directive instance.

Learn more about selectors.

Change All Calendars

First, remove all references to <app-company-calendar></app-company-calendar>, and switch back to <kendo-calendar></kendo-calendar>. We’re back to having the full power from <kendo-calendar>.

<div>
	<h3>Subscribe</h3>
	<kendo-calendar></kendo-calendar>
</div>
<div>
  <h3>Purchase</h3>
  <kendo-calendar></kendo-calendar>
</div>
<div>
  <h3>Birthday</h3>
  <kendo-calendar></kendo-calendar>
</div>

Next, update the selector to <kendo-calendar> to trigger the directive instance. Inject the CalendarComponent in the constructor and set the property value to the current date.

The Calendar Component instance shows all properties and the methods adapt it to our business requirements.

import { Directive } from '@angular/core';
import { CalendarComponent } from '@progress/kendo-angular-dateinputs';

@Directive({
  selector: 'kendo-calendar'
})
export class CurrentDateDirective {

  constructor(private kendoCalendar: CalendarComponent) {
    this.kendoCalendar.value = new Date();
   }

}

Exclude or Include

We have scenarios to affect calendars with or without attributes. For example, the kendo-calendar with the asCompanyCalendar directive hides the calendar navigation.

The selector kendo-calendar[as-company-calendar] finds all kendo-calendar instances with the as-company-calendar attribute to trigger the directive instance.

To exclude, use :not in the selector, find all elements without the as-company-calendar attribute. So that would look like: kendo-calendar:not(as-company-calendar) .

import { Directive } from '@angular/core';
import { CalendarComponent } from '@progress/kendo-angular-dateinputs';

@Directive({
  selector: 'kendo-calendar[as-company-calendar]'
})
export class AscompanycalendarDirective {

  constructor(private kendoCalendar: CalendarComponent) {
    this.kendoCalendar.value = new Date();
    this.kendoCalendar.navigation = false;
   }

}

Add the directive to the kendo-calendar component to trigger the directive Ascompanycalendar.

<div>
<h3>Subscribe</h3>
<kendo-calendar as-company-calendar></kendo-calendar>
</div>

<div>
  <h3>Purchase</h3>
  <kendo-calendar as-company-calendar></kendo-calendar>
</div>

<div>
  <h3>Birthday</h3>
  <kendo-calendar></kendo-calendar>
</div>

We have the same behavior in all calendars without adding an extra component and with Kendo UI’s power!

Learn more about Angular Directives.

Recap

We learned how to implement <kendo-calendar> using directives to use Kendo UI’s full power, change its behavior, and give a list of benefits:

  • The code is easy to read (<kendo-calendar as-company-calendar></kendo-calendar>).
  • We have an absolute separation between the company requirements.
  • We can use the component without using a container.
  • We can use nested directives to cover multiple cases.

The full code example link: GitHub.


About the Author

Dany Paredes

Dany Paredes is a Google Developer Expert on Angular and Progress Champion. He loves sharing content and writing articles about Angular, TypeScript and testing on his blog and on Twitter (@danywalls).

Related Posts

Comments

Comments are disabled in preview mode.