Всем привет, меня зовут Дэн, я молодой веб-разработчик, увлеченный JavaScript. Сейчас я разработчик на стороне интерфейса и делаю волшебные вещи в Angular 5. Эта статья адресована новичкам, это мой первый урок по программированию, особенно - Как создавать загрузчик изображений, который вы сможете использовать в любом следующем проекте. Хорошо, поехали.

Создать новый компонент

Обычно этот компонент должен быть помещен в общий модуль, потому что вы должны получить к нему доступ глобально.

ng g c image-uploader

Создать простой загрузчик изображений

После создания компонента откройте image-uploader.component.html и создайте простой ввод.

<input type="file" id="uploader"/>

В моем случае загрузчик - это простой значок, расположенный по центру родительского блока. Я использую значок FontAwesome (вы можете заменить его любым изображением или текстом) и любые простые стили.

<label class="uploader-circle">
  <i class="fas fa-plus"></i>
  <input type="file" id="uploader"/>
</label>

ДОПОЛНИТЕЛЬНО: если вы хотите использовать значок FontAwesome, импортируйте эту библиотеку в index.html.

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.8/css/all.css" integrity="sha384-3AB7yXWz4OeoZcPbieVW64vVXEwADiYyAEhwilzWsLw+9FgqpyjjStpPnpBO8o8S"
      crossorigin="anonymous">

Откройте image-uploader.component.scss и добавьте следующие стили:

input {
  display: none;
}

label.uploader-circle {
  $size: 23px;
  cursor: pointer;
  width: $size;
  height: $size;
  line-height: 19px;
  text-align: center;
  border-radius: 100%;
  // Using position attribute
  position: absolute; // Give absolute position
  top: 50%; // Vertical center
  left: 50%; // Horizontal center
  transform: translate(-50%, -50%); // The icon is centered by the style regardless of the size of the parent
  transition: all .2s ease-out;

  i {
    font-size: 24px;
    color: #000;
  }
}

Теперь наш загрузчик изображений выглядит так:

Создание функционала и подключение API

Прежде всего, мы используем HttpClient для запроса, для этого мы импортируем HttpClientModule. Для дальнейшего использования компонента мы его экспортируем.

import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {HttpClientModule} from '@angular/common/http'; // Import Path


@NgModule({
  imports: [
    CommonModule,
    HttpClientModule // Import HttpClientModule
  ],
  declarations: [
    ImageUploaderComponent
  ],
  exports: [
    ImageUploaderComponent // Export Image Uplaoder
  ],
  providers: []
})
export class SharedModule {
}

Во-вторых, откройте image-uploader.component.ts и импортируйте в конструктор HttpClient.

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

@Component({
  selector: 'app-image-uploader',
  templateUrl: './image-uploader.component.html',
  styleUrls: ['./image-uploader.component.scss']
})
export class ImageUploaderComponent {

  constructor(private http: HttpClient) {
  }


}

Создайте метод, который получит параметры загрузчика:

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

@Component({
  selector: 'app-image-uploader',
  templateUrl: './image-uploader.component.html',
  styleUrls: ['./image-uploader.component.scss']
})
export class ImageUploaderComponent {

  selectedFile: File = null;

  constructor(private http: HttpClient) {
  }

  /**
   * Validate uploader params
   * @param event
   */
  public onFileSelected(event) {
    this.selectedFile = <File>event.target.files[0];
    if (this.selectedFile) {
      // If selected file exist make upload request
    }
  }

}

Вызовите этот метод при изменении параметров загрузчика и отправьте $ event.

<label class="uploader-circle">
  <i class="fas fa-plus"></i>
  <input type="file" (change)="onFileSelected($event)" id="uploader"/>
</label>

ДОПОЛНИТЕЛЬНО: если мы хотим, чтобы загрузчик загружал только изображение, мы используем атрибут input accept.

<input type="file" (change)="onFileSelected($event)" accept="image/*" id="uploader"/>

Отправить запрос на сервер на загрузку изображения.

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


@Component({
  selector: 'app-image-uploader',
  templateUrl: './image-uploader.component.html',
  styleUrls: ['./image-uploader.component.scss']
})
export class ImageUploaderComponent {

  selectedFile: File = null;
  public image: any;

  constructor(private http: HttpClient) {
  }

  /**
   * Validate uploader params
   * @param event
   */
  public onFileSelected(event) {
    this.selectedFile = <File>event.target.files[0];
    if (this.selectedFile) {
      return this.upload();
    }
  }


  /**
   * Upload image to server and receive image object
   */
  upload() {
    const fd = new FormData();
    fd.append('image', this.selectedFile, this.selectedFile.name);
    this.http.post('http://example.com/upload/image', fd).subscribe((res: any) => {
      this.image = res.data;
    }, (err: any) => {
        // Show error message or make something.
    });
  }

}

В нашем случае, если все в порядке, наш запрос возвращает нам следующий ответ:

Последнее, что нам нужно сделать, это вернуть ответ в нашу форму. Давайте сделаем это с помощью Angular Output. Это означает, что каждый раз, когда мы загружаем изображение, мы получаем ответ от сервера на форму.

import {Component, EventEmitter, Output} from '@angular/core';
import {HttpClient} from '@angular/common/http';


@Component({
  selector: 'app-image-uploader',
  templateUrl: './image-uploader.component.html',
  styleUrls: ['./image-uploader.component.scss']
})
export class ImageUploaderComponent {

  selectedFile: File = null;
  @Output() event = new EventEmitter();
  public image: any;

  constructor(private http: HttpClient) {
  }

  /**
   *  Validate uploader params
   * @param event
   */
  public onFileSelected(event) {
    this.selectedFile = <File>event.target.files[0];
    if (this.selectedFile) {
      return this.upload();
    }
  }


  /**
   * Upload image to server and receive image object
   */
  upload() {
    const fd = new FormData();
    fd.append('image', this.selectedFile, this.selectedFile.name);
    this.http.post('http://example.com/upload/image', fd).subscribe((res: any) => {
      this.image = res.data;
      this.event.emit(this.image);
    }, (err: any) => {
      // Show error message or make something.
    });
  }

}

Как мы используем загрузчик изображений

Когда у нас есть форма с загрузчиком изображений, мы просто ее используем.

<form>
  <input type="text" placeholder="Name" />
  <div class="uploader">
    <app-image-uploader (event)="giveImage($event)"></app-image-uploader>
  </div>
</form>

Примечание: родительский элемент загрузчика изображения должен иметь position: relative;

В методе giveImage мы получаем ответ от загрузчика изображений ..

public giveImage(event)
{
  console.log(event);
}

Конечный результат

Вывод

Если мы создадим загрузчик как отдельный компонент, мы сможем использовать его в любой форме, которую мы используем. Его легко поддерживать и добавлять новые функции.

Спасибо за внимание, ждем ваших отзывов.