Transform Inputs Properties in Angular Easy
Tags: angular, typescript, javascript, frontend
Published: 2023-11-11 16:43:33

When building components, defining the interfaces to be used by consumers is often challenging. We need to consider the information that must be passed between components and, at times, how it is processed.

At times, we expose interfaces solely due to an internal contract, but this is not an ideal approach. For instance, yesterday, I was constructing an article about the Kendo Scheduler. In my example, I developed an application that allows users to select course dates and add them to the calendar.

The calendar makes use of the Kendo Scheduler component, which requires a SchedulerEvent interface to display the event. In the context of my application, the key interface is 'Course.'

```typescript
export type Course = {
  id: string;
  start: Date;
  title: string;
  description: string;
  done: boolean;
};
```

When other developers work with the component, they should expect to pass an array of courses.

```xml
<courses-schedule [courses]="courses">
```

I wanted to display these courses in the Kendo Scheduler, but the contract with the Kendo Scheduler is slightly different because it uses the SchedulerEvent interface.

* Why should I type my courses as a SchedulerEvent Interface?
    
* How can I transform my courses into a Scheduler Interface?
    

## Transform Inputs

From version 16.1.0, Angular introduced [`transform`](https://angular.io/api/core/Input#transform) a powerful and convenient feature for transforming input properties. This feature is particularly useful when you need to transform data.

```typescript
@Input({ transform: toScheduleEvent }) courses: Course[] = [];
```

The transform option provides a straightforward method for data conversion. It will keep the signature with the courses interface and transform the course into the SchedulerEvent Interface. It makes the component user-friendly and simplifies the process of converting input data into other entities.

> Read more about [transform](https://angular.io/api/core/Input#transform)

## **Encapsulating Kendo's SchedulerEvent**

We have two goals to reach:

1. Continue exposing my input property course with type `Course`.
    
2. Transform the input courses into `SchedulerEvent`.
    

```xml
<app-calendar [courses]="courses"></app-calendar>
```

Using the `transform`, we can convert the course data while hiding the mapping logic needed by the scheduler.

The input property maintains its type, while the transform employs the function `toScheduleEvent` to execute the transformation.

```typescript
  @Input({ transform: toScheduleEvent }) courses: Course[] = [];
```

Within the `toScheduleEvent` function, we utilize the map function to transform the course into the SchedulerEvent interface.

```typescript
function toScheduleEvent(courses: Course[]): SchedulerEvent[] {
  return courses.map(course => ({
    id: course.id,
    title: course.title,
    start: course.start,
    end: new Date(course.start.getTime() + 2 * 60 * 60 * 1000), 
    isAllDay: false
    description: course.description
  }));
}
```

The final code appears as follows:

```typescript
import { Component, Input } from '@angular/core';
import { SchedulerEvent } from '@progress/kendo-angular-scheduler';

@Component({
  selector: 'app-calendar',
  standalone: true,
  imports: [CommonModule, MonthViewModule, SchedulerModule],
  templateUrl: './calendar.component.html',
  styleUrls: ['./calendar.component.scss']
})
export class CalendarComponent {
  @Input({ transform: toScheduleEvent }) courses: Course[] = [];
}

function toScheduleEvent(courses: Course[]): SchedulerEvent[] {
  return courses.map(course => ({
    id: course.id,
    title: course.title,
    start: course.start,
    end: new Date(course.start.getTime() + 2 * 60 * 60 * 1000), 
    isAllDay: false
    description: course.description
  }));
}
```

Done! We've exposed the Course interface, but within my component, I maintain my contract with the Kendo Scheduler with no pain!

## Recap

Done! Now, with this feature, we save time by not having to declare getters, and Angular assists us with a convenient method for transforming inputs. This simplifies data conversion and demonstrates how to encapsulate types and convert them to other types using the transform feature.

***Happy Transform!!***