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.
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:
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:
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.
Our first approach works, but it has a list of side effects for our team:
It is too costly only for customizing our UI. Let’s try to take another approach.
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.
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();
}
}
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.
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:
<kendo-calendar as-company-calendar></kendo-calendar>
).The full code example link: GitHub.
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).