Создание элемента-слайдера изображений с использованием Angular

1. Введение

Автор: приглашенный автор Ааюш Арора

Элементы Angular — это компоненты Angular, упакованные как пользовательские элементы. В настоящее время они поддерживаются Chrome, Opera и Safari, а также доступны в других браузерах посредством полифиллов. Эти элементы могут использовать всю инфраструктуру Angular с общим интерфейсом Angular и стратегией обнаружения изменений. После регистрации эти элементы можно использовать в браузере.

Эта лабораторная работа проведет вас через создание собственного компонента Angular для слайдера изображений, а затем поможет преобразовать его в элемент Angular, чтобы он мог работать вне Angular Framework.

Что вы будете строить

В этой лабораторной работе вы создадите элемент-слайдер изображений с помощью Angular. Ваш элемент будет:

  • работать как HTML-элемент в браузере
  • Возможность подключения к любому фреймворку, взаимодействующему с DOM.

Чему вы научитесь

  • Как создать пользовательский компонент слайдера изображений
  • Как преобразовать пользовательский компонент слайдера изображений в пользовательский элемент
  • Как упаковать компонент, чтобы он работал внутри браузера

Что вам понадобится

  • Последняя версия angular-cli .
  • Пример кода
  • Текстовый редактор
  • Базовые знания компонентов Angular

Эта практическая работа посвящена элементам Angular. Нерелевантные концепции и блоки кода опущены и предоставлены для простого копирования и вставки.

2. Подготовка

Загрузить код

Чтобы загрузить весь код для этой лабораторной работы, щелкните следующую ссылку:

Распакуйте скачанный zip-архив. Будет распакована корневая папка (angular-element-codelab-master) , содержащая:

две папки (image-slider) и (image-slider-finished) . Всю работу по кодированию мы будем выполнять в папке с именем image-slider.

Запуск проекта

Для запуска проекта необходимо выполнить команду (ng-serve) из корневого каталога (image-slider).

После загрузки приложения вы увидите следующее:

19ffd082e2f024a5.png

3. Создание пользовательского компонента Image-Slider?

Как создать слайдер изображений?

Для этого слайдера изображений привяжите кнопки с помощью углового клика. Мы создадим массив объектов, содержащий изображения, alt-теги, ссылки и т.д. Мы разместим эти изображения одно под другим в контейнере и будем перемещать контейнер по щелчку.

Мы собираемся создать компонент слайдера изображений, а затем преобразуем его в угловой элемент.

  • Контейнер для изображений и заголовков.
  • Массив, содержащий данные
  • Шаблон для привязки данных

4. Реализуйте компонент слайдера изображений.

Существует несколько способов начать работу над любым проектом. В данном случае, чтобы максимально упростить наш проект и сосредоточиться на элементах Angular, мы предоставили вам базовый код вместе с CSS.

Создание массива и сервиса данных

Помните, sliderArray будет содержать:

  • Ключ img для URL-адреса изображения в слайдере
  • Тег alt для указания alt для изображения
  • Текст, содержащий описание изображения.

Файл data.json , который уже находится в каталоге src/assets должен выглядеть примерно так.

sliderArray = [
 {img: 'http://bloquo.cc/img/works/1.jpg', alt: '', text: '365 Days Of weddings a year'},
 {img: 'http://bloquo.cc/img/works/2.jpg', alt: '',  text: '365 Days Of weddings a year'},
 {img: 'http://bloquo.cc/img/works/3.jpg', alt: '', text: '365 Days Of weddings a year'},
 {img: 'http://bloquo.cc/img/works/4.jpg', alt: '',  text: '365 Days Of weddings a year'},
 {img: 'http://bloquo.cc/img/works/5.jpg', alt: '', text: '365 Days Of weddings a year'}
];

Нам нужно получить эти данные в нашем компоненте с помощью сервиса. В файле data.service.ts мы напишем метод getData() используя модуль httpClient из @angular/common/http который будет получать данные из массива, созданного выше.

 
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'

const URL = '../assets/data.json';

@Injectable({
 providedIn: 'root'
})
export class DataService {

 constructor(private http: HttpClient) {}

 getData() {
   return this.http.get(URL)
 }
}

Извлечение данных из службы данных

Нам нужно импортировать нашу службу внутрь компонента, а затем мы можем подписаться на наблюдаемый объект, чтобы получить объект из data.json

Для этого нам необходимо выполнить три шага:

  • Инициализация массива компонентов
  • Подписка на Observable, возвращаемый функцией getData()
  • Создайте интерфейс Result для проверки типов данных после подписки на наблюдаемый объект.
  • Назначьте данные массиву компонентов.

Инициализация массива компонентов

Мы объявим и инициализируем массив компонентов внутри slider.component.ts , который представляет собой массив объектов:

Заявить:

sliderArray: object[];

Для инициализации:

constructor(private data: DataService) {
 this.sliderArray = [];
}

Далее нам нужно импортировать и инициализировать наш сервис внутри конструктора.

constructor(private data: DataService) {}

Теперь мы готовы использовать нашу службу и вызывать ее методы.

Получение данных из Data Service

Чтобы получить данные из сервиса, мы вызовем метод getData() и подпишемся на наблюдаемый объект, который он вернет, мы также создадим интерфейс Result, чтобы мы могли проверить тип и убедиться, что мы получаем правильные данные.

Мы сделаем это внутри метода ngOnInit :

this.data.getData().subscribe((result: Result)=>{
})

Назначение данных массиву компонентов

В конце мы присвоим данные массиву компонентов:

this.data.getData().subscribe((result: Result)=>{  
  this.sliderArray = result.sliderArray;
})

Как только мы получим данные из массива нашего компонента, мы сможем связать наш шаблон с этими данными.

В slider.component.html, у нас уже есть HTML-шаблон. Следующий шаг — связать этот шаблон с sliderArray .

5. Привязка данных к шаблону

Мы свяжем данные с шаблоном, используя директиву *ngFor , и, наконец, добавим преобразования в шаблон, чтобы заставить ползунок работать.

Этот процесс состоит из трех шагов:

  • Привязка sliderArray к шаблону
  • Добавление привязки событий для кнопок-ползунков
  • Добавление CSS-преобразований с использованием ngStyle и ngClass

Привязка slideArray к компоненту

У нас есть контейнер, содержащий img-container , a text-container и a slider.

Мы свяжем данные во всех трех контейнерах с помощью директивы *ngFor

<div class="container">
 <div class="img-container" *ngFor="let i of sliderArray; let select = index;">
   <img src="{{i.img}}" alt="{{i.alt}}" >
 </div>

 <div>
   <div class="text-container">
     <div class="page-text" *ngFor="let i of sliderArray;let select = index;">
       <h3>{{i.text}}</h3>
     </div>
   </div>
 </div>

</div>

<div class="slider">
 <div class="slide-button-parent-container" *ngFor="let i of sliderArray; let x =index">
    <div class="select-box">
     <div class="slide-button">
     </div>
    </div>
 </div>
</div>

Привязка события к slideArray

После привязки данных мы привяжем событие нажатия к каждой кнопке слайдера, используя Angular click binding . Мы создадим функцию selected(x) , где x — индекс массива.

selected(x) {
 this.downSelected(x);
 this.selectedIndex = x;
}

downSelected(i) {
  this.transform =  100 - (i) * 50;
  this.selectedIndex = this.selectedIndex + 1;
  if(this.selectedIndex > 4) {
    this.selectedIndex = 0;
  }
}

Что следует здесь запомнить:

  • Функция с пониженным значением уменьшает значение свойства преобразования в пятьдесят раз относительно индекса, переданного при щелчке selected функции.
  • Эта логика переводит текстовый контейнер в значения 100%, 50%, -50%, -100%, что приводит к четырем различным состояниям.

Добавление CSS-преобразований с использованием ngStyle и ngClass

Изначально мы устанавливаем для всех изображений непрозрачность, равную нулю, и добавляем класс selected с помощью ngClass directive когда индекс выбранного изображения становится равным индексу изображения. Этот selected класс добавляет к изображению непрозрачность, равную единице, делая его видимым для пользователя.

<div class="img-container"  *ngFor="let i of sliderArray; let select = index;"
      [ngClass]="{'selected': select == selectedIndex}">
</div>

После этого мы переведем текстовый контейнер в соответствии со значением transform , вычисленным с помощью функции select() .

<div [ngStyle]="{'transform': 'translateY('+ transform + '%' +')', 'transition': '.8s'}">
</div>

После выполнения всех этих шагов вы можете увидеть окончательный код, как показано ниже:

<div class="container">
 <div class="img-container"  *ngFor="let i of sliderArray; let select = index;"
      [ngClass]="{'selected': select == selectedIndex}">
   <img src="{{i.img}}" alt="{{i.alt}}" >
 </div>

 <!--</div>-->
 <div [ngStyle]="{'transform': 'translateY('+ transform + '%' +')', 'transition': '.8s'}">
   <div class="text-container">
     <div class="page-text" *ngFor="let i of sliderArray;let select = index;" [ngClass]="{'selected': select == selectedIndex}">
       <h3>{{i.text}}</h3>
     </div>
   </div>
 </div>

</div>

<div class="slider">
 <div class="slide-button-parent-container"  *ngFor="let i of sliderArray; let x =index" (click)="selected(x)" >
    <div class="select-box">
     <div   class="slide-button" [ngClass]="{'slide-button-select': x == selectedIndex}" >
     </div>
    </div>
 </div>
</div>

6. Преобразование компонента в угловой элемент

Эта процедура состоит из пяти этапов:

  • Использование Shadow DOM для Angular Element
  • Использование entryComponents
  • Импорт и использование модуля CreateCustomElement из @angular/elements
  • Определение нашего custom-element
  • Запуск метода ngDoBootstrap

Использование Shadow DOM для углового элемента

Теперь наш слайдер изображений работает, нам просто нужно сделать его Angular Element .

Самое интересное, что для создания компонента DOM, теневого DOM, требуется лишь небольшое изменение.

Нам необходимо импортировать модуль ViewEncapsulation и использовать из него метод ShadowDom .

@Component({
 selector: 'app-slider',
 templateUrl: './slider.component.html',
 styleUrls: ['./slider.component.css'],
 encapsulation: ViewEncapsulation.ShadowDom
})

Использование entryComponents

Компонент входа — это компонент, который Angular загружает императивно. Компонент входа указывается путём его загрузки в NgModule.

Здесь мы укажем наш SliderComponent в массиве entryComponents внутри @NgModule

@NgModule({
 declarations: [
   SliderComponent
 ],
 imports: [
   BrowserModule,
   HttpClientModule
 ]
})

Импорт и использование модуля createCustomElement

Здесь нам нужно использовать модуль createCustomElement из @angular/elements. SliderComponent, необходимо передать в качестве параметра функции createCustomElement . После этого нужно зарегистрировать slider в DOM.

import { createCustomElement } from '@angular/elements';

export class AppModule {
 constructor(private injector: Injector) {
   const slider = createCustomElement(SliderComponent, { injector });
    }
}

Чтобы зарегистрировать ползунок как элемент DOM, мы определим его с помощью метода customElements.define .

customElements.define('motley-slider', slider);

Наконец, нам нужно загрузить этот пользовательский элемент с помощью метода ngDoBootstrap() . Полный код будет выглядеть так:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, Injector } from '@angular/core';
import { createCustomElement } from '@angular/elements';
import { SliderComponent } from './slider/slider.component';
import { HttpClientModule} from "@angular/common/http";

@NgModule({
 declarations: [
   SliderComponent
 ],
 imports: [
   BrowserModule,
   HttpClientModule
 ]
})
export class AppModule {
 constructor(private injector: Injector) {
   const slider = createCustomElement(SliderComponent, { injector });
   customElements.define('motley-slider', slider);
 }

 ngDoBootstrap() {}

}

Упаковка элемента Angular

Нам необходимо изменить package.json с помощью наших новых команд, мы изменим объект скрипта внутри файла package.json .

Давайте проверим наш измененный объект скрипта:

"scripts": {
 "ng": "ng",
 "start": "ng serve",
 "build": "ng build --prod --output-hashing=none",
 "package": "cat dist/my-app/{runtime,polyfills,scripts,main}.js | gzip > elements.js.gz",
 "serve": "http-server",
 "test": "ng test",
 "lint": "ng lint",
 "e2e": "ng e2e"
}

Теперь мы можем выполнить команду ng build & ng package , а затем команду ng serve, чтобы обработать папку dist/, созданную командой build. Кроме того, мы можем использовать gzip , полученный командой ng package , распаковать его и опубликовать как npm module .