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).