Tworzenie elementu suwaka obrazów za pomocą Angulara

1. Wprowadzenie

Autor gościnny: Aayush Arora

Angular Elements to komponenty Angulara spakowane jako elementy niestandardowe. Są one obecnie obsługiwane przez Chrome, Operę i Safari, a w innych przeglądarkach są dostępne dzięki polyfillom. Te elementy mogą korzystać z całej infrastruktury Angulara ze wspólnym interfejsem Angulara i strategią wykrywania zmian. Po zarejestrowaniu można ich używać w przeglądarce.

W tym samouczku dowiesz się, jak utworzyć własny komponent Angulara do przesuwania obrazów, a następnie przekształcić go w element Angulara, aby mógł działać poza platformą Angular.

Co utworzysz

W tym ćwiczeniu w Codelabs utworzysz element suwaka obrazów za pomocą Angulara. Twój element wi:

  • działać jak element HTML w przeglądarce,
  • Można go podłączyć do dowolnego frameworka, który komunikuje się z DOM.

Czego się nauczysz

  • Jak utworzyć komponent niestandardowy w postaci suwaka obrazów
  • Jak przekształcić komponent niestandardowy image-slider w element niestandardowy
  • Jak spakować komponent, aby działał w przeglądarce

Czego potrzebujesz

Ten codelab dotyczy elementów Angulara. Nieistotne koncepcje i bloki kodu zostały pominięte. Można je po prostu skopiować i wkleić.

2. Przygotowania

Pobieranie kodu

Aby pobrać cały kod do tego laboratorium, kliknij ten link:

Rozpakuj pobrany plik ZIP. Spowoduje to rozpakowanie folderu głównego (angular-element-codelab-master), który zawiera

dwa foldery: (image-slider)(image-slider-finished). Całą pracę związaną z kodowaniem będziemy wykonywać w katalogu o nazwie image-slider.

Realizacja projektu

Aby uruchomić projekt, musisz uruchomić polecenie ( ng-serve ) w katalogu głównym ( image-slider ).

Po uruchomieniu aplikacji zobaczysz:

19ffd082e2f024a5.png

3. Tworzenie komponentu niestandardowego Image-Slider

Jak utworzyć suwak obrazów?

W przypadku tego suwaka obrazów powiąż przyciski za pomocą wiązania kliknięcia Angular. Utworzymy tablicę obiektów zawierającą obrazy, tagi alt, linki itp. Umieścimy te obrazy jeden pod drugim w kontenerze i przetłumaczymy kontener po kliknięciu.

Utworzymy komponent suwaka obrazów, a następnie przekształcimy go w element Angulara.

  • Kontener na obrazy i tytuły.
  • tablica zawierająca dane;
  • Szablon do powiązania danych

4. Implementowanie komponentu suwaka obrazów

Istnieje wiele sposobów na rozpoczęcie dowolnego projektu. W tym przypadku, aby jak najbardziej uprościć projekt i skoncentrować się na elementach Angular, udostępniliśmy podstawowy kod wraz z CSS.

Tworzenie tablicy i usługi danych

Pamiętaj, że tablica sliderArray będzie zawierać:

  • Klucz img dla adresu URL obrazu w suwaku.
  • Tag alt, który zawiera tekst alternatywny obrazu.
  • Tekst opisujący obraz.

Plik data.json, który znajduje się już w katalogu src/assets, powinien wyglądać mniej więcej tak:

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'}
];

Musimy pobrać te dane w naszym komponencie za pomocą usługi. W pliku data.service.ts napiszemy metodę getData(), która będzie korzystać z modułu httpClient@angular/common/http i pobierać dane z utworzonej powyżej tablicy.

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

Pobieranie danych z usługi danych

Musimy zaimportować usługę w komponencie, a następnie zasubskrybować obiekt observable, aby pobrać obiekt z data.json.

W tym celu musimy wykonać 3 kroki:

  • Inicjowanie tablicy komponentów
  • Subskrybowanie obiektu Observable zwróconego przez funkcję getData()
  • Utwórz interfejs Result, aby po zasubskrybowaniu obiektu Observable sprawdzić typ danych.
  • Przypisz dane do tablicy komponentów.

Inicjowanie tablicy komponentów

Zadeklarujemy i zainicjujemy tablicę komponentów wewnątrz slider.component.ts, która jest tablicą obiektów:

Aby zadeklarować:

sliderArray: object[];

Aby zainicjować:

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

Następnie musimy zaimportować i zainicjować naszą usługę w konstruktorze.

constructor(private data: DataService) {}

Teraz możemy korzystać z naszej usługi i wywoływać jej metody.

Pobieranie danych z usługi danych

Aby pobrać dane z usługi, wywołamy metodę getData() i zasubskrybujemy zwracany przez nią obiekt observable. Utworzymy też interfejs Result,, aby sprawdzić, czy otrzymujemy prawidłowe dane.

Zrobimy to w metodzie ngOnInit:

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

Przypisywanie danych do tablicy komponentów

Na koniec przypiszemy dane do tablicy komponentów:

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

Gdy dane znajdą się w tablicy komponentu, możemy powiązać szablon z tymi danymi.

W slider.component.html, mamy już szablon HTML. Kolejnym krokiem jest powiązanie tego szablonu z sliderArray.

5. Powiązanie danych z szablonem

Połączymy dane z szablonem za pomocą dyrektywy *ngFor, a następnie dodamy do szablonu przekształcenia, aby suwak działał.

Składa się ona z 3 kroków:

  • Powiązywanie szablonu z elementem sliderArray
  • Dodawanie powiązania zdarzenia dla przycisków suwaka
  • Dodawanie przekształceń CSS za pomocą ngStylengClass

Powiązanie tablicy slideArray z komponentem

Mamy kontener zawierający img-container, a text-container i a slider..

Połączymy dane we wszystkich 3 kontenerach za pomocą dyrektywy *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>

Powiązanie zdarzenia z tablicą slideArray

Po powiązaniu danych powiążemy zdarzenie kliknięcia z każdym przyciskiem suwaka za pomocą funkcji click binding w Angularze. Utworzymy funkcję o nazwie selected(x), gdzie x to indeks tablicy.

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;
  }
}

Ważne informacje:

  • Wybrana funkcja zmniejsza wartość właściwości przekształcenia 50 razy w stosunku do indeksu przekazanego po kliknięciu funkcji selected.
  • Ta logika tłumaczy kontener tekstu na 100%, 50%, -50% i -100%, co daje 4 różne stany.

Dodawanie przekształceń CSS za pomocą ngStyle i ngClass

Początkowo ustawiamy wszystkie obrazy na nieprzezroczyste (wartość 0). Gdy wybrany indeks jest równy indeksowi obrazu, dodajemy klasę selected za pomocą ngClass directive. Ta klasa selected dodaje do obrazu nieprzezroczystość równą 1, dzięki czemu obraz jest widoczny dla użytkownika.

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

Następnie przetłumaczymy kontener tekstu zgodnie z wartością transform obliczoną za pomocą funkcji select().

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

Po wykonaniu wszystkich tych czynności możesz sprawdzić ostateczny kod, jak podano poniżej:

<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. Przekształcanie komponentu w element Angulara

Ta procedura obejmuje 5 kroków:

  • Używanie Shadow DOM w przypadku elementu Angular
  • Korzystanie z entryComponents
  • Importowanie i używanie modułu CreateCustomElement z usługi @angular/elements
  • Definiowanie custom-element
  • Uruchomiono ngDoBootstrap

Używanie modelu Shadow DOM w przypadku elementu Angular

Mamy już działający suwak obrazów, musimy tylko przekształcić go w Angular Element.

Zabawne jest to, że aby przekształcić DOM komponentu w Shadow DOM, wystarczy niewielka zmiana.

Musimy zaimportować moduł ViewEncapsulation i użyć metody ShadowDom.

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

Korzystanie z entryComponents

Komponent Entry to komponent, który Angular wczytuje w sposób imperatywny. Komponent wejściowy określa się przez uruchomienie go w module NgModule.

Tutaj określimy nasz SliderComponent w tablicy entryComponents wewnątrz @NgModule

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

Importowanie i używanie modułu createCustomElement

W tym przypadku musimy użyć modułu createCustomElement@angular/elements.. Musisz użyć SliderComponent, jako parametru funkcji createCustomElement. Następnie musimy zarejestrować element slider w DOM.

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

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

Aby zarejestrować suwak jako element DOM, zdefiniujemy go za pomocą metody customElements.define.

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

Na koniec musimy zainicjować ten element niestandardowy za pomocą metody ngDoBootstrap(). Pełny kod będzie wyglądać tak:

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() {}

}

Pakowanie elementu Angular

Musimy zmodyfikować package.json za pomocą nowych poleceń. W tym celu zmodyfikujemy obiekt skryptu w pliku package.json.

Sprawdźmy zmodyfikowany obiekt skryptu:

"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"
}

Teraz możemy uruchomić polecenie ng build & ng package, a na koniec uruchomimy polecenie ng serve, aby udostępnić folder dist/ wygenerowany za pomocą polecenia build. Możemy też użyć gzip uzyskanego za pomocą polecenia ng package, wyodrębnić go i opublikować jako npm module.