Mục tiêu

Ứng dụng gallery- Nắm bắt được về các thao tác với NgModule và DI trong Angular.

Mô tả- Ứng dụng gallery

Ứng dụng gallery

Hướng dẫn

Bước 1: Khởi tạo project với Angular CLI (nếu đã có project thì có thể bỏ qua)

Các bạn chạy lệnh npm i typescript@2.9.2 -D để cài đặt thư viện typescript nếu phiên bản hiện tại < 2.9.2

Bước 2: Khởi tạo một NgModule tên là image-gallery, và 2 component tên là image-card, image-gallery

ng g m image-gallery

ng g c image-gallery

ng g c image-gallery/image-card

Bước 3: Thay phần template của component vừa tạo bằng đoạn code sau:

image-gallery.component.html:

<div class="gallery-container">
    <div class="gallery-item" *ngFor="let img of listImage">
        <app-image-card [src]="img"></app-image-card>
    </div>
</div>

image-card.component.html:

<div class="card">
    <img *ngIf="src" [src]="src" alt="" class="img-card">
</div>

Bước 4: Code phần logic cho component

image-gallery.component.ts:

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

@Component({
    selector: 'app-image-gallery',
    templateUrl: './image-gallery.component.html',
    styleUrls: ['./image-gallery.component.scss']
})
export class ImageGalleryComponent implements OnInit {
    listImage = [
        'https://via.placeholder.com/1280x420/e91e63/ffffff?text=1',
        'https://via.placeholder.com/1280x420/e91e63/ffffff?text=2',
        'https://via.placeholder.com/1280x420/e91e63/ffffff?text=3',
        'https://via.placeholder.com/1280x420/e91e63/ffffff?text=4'
    ];
    constructor() { }

    ngOnInit() {
    }

}

image-card.component.ts:

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

@Component({
    selector: 'app-image-card',
    templateUrl: './image-card.component.html',
    styleUrls: ['./image-card.component.scss']
})
export class ImageCardComponent implements OnInit {
    @Input() src = '';
    constructor() { }

    ngOnInit() {
    }

}

Bước 5: Thêm style cho các component vừa tạo:

image-gallery.component.scss:

.gallery-container {
    display: flex;
    flex-wrap: wrap;
}

.gallery-item {
    flex: 1;
    max-width: 25%;
    padding: 0 5px
}

image-card.component.scss:

:host {
    display: block;
}

.card {
    box-shadow: 0 3px 1px -2px rgba(0,0,0,.2), 0 2px 2px 0 rgba(0,0,0,.14), 0 1px 5px 0 rgba(0,0,0,.12);
}
.img-card {
    max-width: 100%;
    display: block;
}

Bước 6: Thêm vào image-gallery.module.ts:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ImageGalleryComponent } from './image-gallery.component';
import { ImageCardComponent } from './image-card/image-card.component';

@NgModule({
    imports: [
        CommonModule
    ],
    declarations: [ImageGalleryComponent, ImageCardComponent],
    exports: [ImageGalleryComponent]
})
export class ImageGalleryModule { }

Bước 7: Thêm vào app.component.html

<app-image-gallery></app-image-gallery>

Bước 8: Thêm vào app.module.ts

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        ImageGalleryModule,
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

Bước 9: Kiểm tra kết quả hiển thị trên trình duyệt

Bước 10: Thêm mới file src/app/image-gallery/token.ts

import { InjectionToken } from '@angular/core';

export const GalleryConfig = new InjectionToken<number>('GalleryConfig');

Bước 11: Update src/app/image-gallery/image-gallery.component.ts

import { Component, OnInit, Inject, Optional } from '@angular/core';
import { GalleryConfig } from './token';

@Component({
    selector: 'app-image-gallery',
    templateUrl: './image-gallery.component.html',
    styleUrls: ['./image-gallery.component.scss']
})
export class ImageGalleryComponent implements OnInit {
    listImage = [
        'https://via.placeholder.com/1280x420/e91e63/ffffff?text=1',
        'https://via.placeholder.com/1280x420/e91e63/ffffff?text=2',
        'https://via.placeholder.com/1280x420/e91e63/ffffff?text=3',
        'https://via.placeholder.com/1280x420/e91e63/ffffff?text=4'
    ];
    itemWidth: number;
    config = 4;
    constructor(
        @Inject(GalleryConfig)
        @Optional()
            config: number
    ) {
        if (config) {
            this.config = config;
        }
    }

    ngOnInit() {
        this.itemWidth = 100 / this.config;
    }
}

Bước 12: Update src/app/image-gallery/image-gallery.component.html

<div class="gallery-container">
    <div class="gallery-item" *ngFor="let img of listImage"
         [style.max-width.%]="itemWidth" [style.flex-basis.%]="itemWidth">
        <app-image-card [src]="img"></app-image-card>
    </div>
</div>

Bước 13: Update src/app/image-gallery/image-gallery.component.scss

.gallery-container {
    display: flex;
    flex-wrap: wrap;
}

.gallery-item {
    flex: 1;
    max-width: 25%;
    padding: 5px
}

Bước 14: Thêm vào app.module.ts

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        ImageGalleryModule,
    ],
    providers: [
        {provide: GalleryConfig, useValue: 2}
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

Bước 15: Kiểm tra kết quả.

Do chúng ta đã có config một token ở AppModule, nên lúc này gallery chỉ hiển thị 2 phần tử 1 hàng.

Mã nguồn tham khảo: https://github.com/codegym-vn/angular-training/tree/master/ngmodule-dependency-injection/src/app

Trên đây CodeGym đã cùng với bạn luyện tập về component data binding trong Angular. Hãy chụp ảnh màn hình và nộp bài thực hành của bạn trên CodeGymX để cùng nhau luyện tập nhé!

Exit mobile version