Getting Started with Kendo UI for Angular Card

The Card component represents any content and actions about a single subject.

It provides clarity, categorization and an attractive way of presenting content.

Basic Usage

The following example demonstrates the Card in action.

import { Component, Input } from '@angular/core';

@Component({
    selector: 'scrollview-card',
    template: `
        <kendo-card [width]="'260px'">
            <kendo-card-header class="k-hbox">
                <kendo-avatar width="40px" height="40px" [imageSrc]="card.thumbnailSrc" [shape]="'circle'"></kendo-avatar>
                <div>
                    <h1 kendoCardTitle>{{ card.headerTitle }}</h1>
                    <p kendoCardSubtitle>{{ card.headerSubtitle }}</p>
                </div>
            </kendo-card-header>

            <kendo-scrollview
                *ngIf="card.scrollViewItems"
                kendoCardMedia
                [data]="card.scrollViewItems"
                [width]="'100%'"
                [height]="'185px'"
                [arrows]="true"
                [pageable]="true">
                <ng-template let-item="item">
                    <img src='{{ item.url }}' alt='{{ item.title }}' [ngStyle]="{ minWidth: '100%' }" draggable="false" />
                </ng-template>
            </kendo-scrollview>

            <kendo-card-actions>
                <comment-actions [card]="card"></comment-actions>
            </kendo-card-actions>

            <hr kendoCardSeparator *ngIf="card.comments.length && card.commentsExpanded">
            <kendo-card-body *ngIf="card.commentsExpanded">
                <post-comment [card]="card"></post-comment>
            </kendo-card-body>
        </kendo-card>
    `
})
export class ScrollViewCardComponent {
    @Input() public card: any;
}
import { Component, Input } from '@angular/core';

import { CardComponent } from '@progress/kendo-angular-layout';

@Component({
    selector: 'comment-actions',
    template: `
        <div>
            <button class="k-button k-flat" (click)="postLikesCount(card)">
                <span [ngClass]="postHeartIcon(card)"></span>
            </button>
            <button class="k-button k-flat" (click)="commentClick(card)">
                <span class="k-icon k-i-comment"></span>
            </button>
            <button class="k-button k-flat"><span class="k-icon k-i-share"></span></button>
        </div>
        <span class="post-likes-count">{{ card.postLikes }} likes</span>
    `
})
export class CommentActionsComponent {
    @Input() public card: CardComponent;

    public commentClick(card: CardComponent): void {
        card.commentsExpanded = !card.commentsExpanded;
    }

    public postLikesCount(card: CardComponent): void {
        if (card.postLiked) {
            card.postLikes -= 1;
        } else {
            card.postLikes += 1;
        }

        card.postLiked = !card.postLiked;
    }

    public postHeartIcon(card: CardComponent): string {
        return card.postLiked ? 'k-icon k-i-heart' : 'k-icon k-i-heart-outline';
    }
}
import { Component, Input } from '@angular/core';

import { CardComponent } from '@progress/kendo-angular-layout';

@Component({
    selector: 'post-comment',
    template: `
        <div *ngIf="card.comments.length">
            <div class="card-comment-wrapper">
                <div class="box" *ngFor="let comment of card.comments">
                    <div class="card-comment-container">
                        <kendo-avatar
                            class="card-comment-thumbnail"
                            [initials]="'EG'"
                            [shape]="'circle'"
                            [cssStyle]="{ color: 'white' }"
                        >
                        </kendo-avatar>
                        <div class="comment-box">
                            <span class="comment-text">{{ comment.text }}</span>
                            <span class="time">1s ago<span>{{ comment.likes }} like</span></span>
                        </div>
                    </div>
                    <button class="k-button k-flat" (click)="commentLikesCount(comment)">
                        <span [ngClass]="commentHeartIcon(comment)"></span>
                    </button>
                </div>
            </div>
        </div>
        <div class="k-hbox card-post-comment-wrapper">
            <textarea class="k-textarea" placeholder="Comment..." [(ngModel)]="card.newCommentTextValue"></textarea>
            <button class="k-button k-primary k-flat" (click)="postComment(card)">Post</button>
        </div>
    `
})
export class PostCommentComponent {
    @Input() public card: CardComponent;

    public commentLikesCount(comment: any): void {
        if (comment.likes > 0) {
            comment.likes -= 1;
        } else {
            comment.likes += 1;
        }
    }

    public commentHeartIcon(comment: any): string {
        if (comment && comment.likes > 0) {
            return 'k-icon k-i-heart';
        } else {
            return 'k-icon k-i-heart-outline';
        }
    }

    public postComment(card: CardComponent): void {
        if (card.newCommentTextValue) {
            const comment = { text: card.newCommentTextValue, likes: 0 };
            card.comments.push(comment);
            card.newCommentTextValue = '';
        }
    }
}
import { Component, ViewEncapsulation } from '@angular/core';

@Component({
    selector: 'my-app',
    template: `
        <div class="card-list">
            <div *ngFor="let card of scrollViewCards">
                <scrollview-card [card]="card"></scrollview-card>
            </div>
        </div>
    `,
    styles: [`
        .card-list {
            display: flex;
            justify-content: space-evenly;
            flex-wrap: wrap;
        }
        .k-textarea {
            resize: none;
        }
        .comment-box {
            display: flex;
            flex-direction: column;
        }
        .card-comment-wrapper .box {
            display: flex;
            justify-content: space-between;
        }
        .card-post-comment-wrapper {
            padding: 16px 16px 0;
        }
        .card-comment-wrapper {
            margin-bottom: 8px;
            padding: 0 16px;
        }
        .card-comment-container {
            padding: 4px 0;
            align-items: center;
            display: flex;
        }
        .comment-box .comment-text {
            font-size: 13px;
            font-weight: bold;
            max-width: 100px;
        }
        .comment-box span {
            font-size: 10px;
            font-weight: normal;
            word-break: break-all;
        }
        .time span {
            margin-left: 8px;
        }
        .box .k-button-icon {
            font-size: 16px;
            align-self: center;
        }
        .post-likes-count {
            font-size: 13px;
            align-self: center;
            color: #656565;
        }
        .k-button.k-flat:focus::after {
            display: none;
        }
        .k-button {
            outline: none;
        }
        .k-button .k-i-heart {
            color: #ff6358;
        }
        .k-card-subtitle .k-icon {
            vertical-align: baseline;
            font-size: 12px;
        }
        .k-card-header .k-card-title+.k-card-subtitle {
            margin-top: 0;
        }
        .k-card-title {
            margin-bottom: 4px;
        }
        .k-card-media li img {
            width: 285px;
        }
        comment-actions {
            width: 100%;
            display: flex;
            justify-content: space-between;
        }
        .k-card-action {
            flex: 0 0 auto;
        }
        .k-avatar {
            margin-right: 1em;
        }
    `],
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    public scrollViewCards: Array<any> = [
        {
            thumbnailSrc: 'https://www.telerik.com/kendo-angular-ui-develop/components/layout/card/assets/bg_flag.jpg',
            headerTitle: 'bg_traditions',
            headerSubtitle: 'Bulgaria, Europe',
            commentsExpanded: false,
            postLiked: false,
            comments: [],
            newCommentTextValue: '',
            postLikes: 674,
            scrollViewItems: [
                { url: 'https://www.telerik.com/kendo-angular-ui-develop/components/layout/card/assets/kukeri.jpg' },
                { url: 'https://www.telerik.com/kendo-angular-ui-develop/components/layout/card/assets/martenitsa.jpg' },
                { url: 'https://www.telerik.com/kendo-angular-ui-develop/components/layout/card/assets/rose_festival.jpg' }
            ]
        },
        {
            thumbnailSrc: 'https://www.telerik.com/kendo-angular-ui-develop/components/layout/card/assets/rila_lakes.jpg',
            headerTitle: 'bg_mountains',
            headerSubtitle: 'Bulgaria, Europe',
            commentsExpanded: false,
            postLiked: false,
            comments: [],
            newCommentTextValue: '',
            postLikes: 962,
            scrollViewItems: [
                { url: 'https://www.telerik.com/kendo-angular-ui-develop/components/layout/card/assets/rila.jpg' },
                { url: 'https://www.telerik.com/kendo-angular-ui-develop/components/layout/card/assets/pamporovo.jpg' },
                { url: 'https://www.telerik.com/kendo-angular-ui-develop/components/layout/card/assets/camping.jpg' }
            ]
        }
    ];

    constructor() { /**/ }
}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { FormsModule } from '@angular/forms';

import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { LayoutModule } from '@progress/kendo-angular-layout';
import { ScrollViewModule } from '@progress/kendo-angular-scrollview';

import { AppComponent } from './app.component';
import { ScrollViewCardComponent } from './scrollview-card.component';
import { PostCommentComponent } from './comment.component';
import { CommentActionsComponent } from './comment-actions.component';

@NgModule({
    declarations: [
        AppComponent,
        ScrollViewCardComponent,
        CommentActionsComponent,
        PostCommentComponent
    ],
    imports: [
        ScrollViewModule,
        FormsModule,
        BrowserModule,
        BrowserAnimationsModule,
        RouterModule.forChild(
            [{
                path: '',
                component: AppComponent
            }]
        ),
        CommonModule,
        LayoutModule
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

enableProdMode();

const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);

The building blocks of the Card component are the following:

Functionality and Features

In this article