- PVSM.RU - https://www.pvsm.ru -

Как сделать поиск пользователей по Github используя Angular

image

Эта статья является ответом на:
Как сделать поиск пользователей по GitHub используя React + RxJS 6 + Recompose [1],
Как сделать поиск пользователей по GitHub без React + RxJS 6 + Recompose [2],
Как сделать поиск пользователей по Github используя VanillaJS [3].

Целью статьи является:
— показать, что на Angular тоже можно быстро написать простое приложение, хотя это не его основной конек,
— показать плюсы приложения на Angular.

Целью статьи НЕ является:
— разжиганеие очередного холивара.

Всем кому интересно прошу под кат.

Подготовка

Для работы с Angular [4] необходимо установить глобально angular CLI [5]

npm install -g @angular/cli

Создаем новое приложение

ng new github-ui
cd github-ui

Сразу создадим комопоненты пользователя и ошибки, и сервис для получения данных с github

ng generate component components/user
ng generate component components/error
ng generate service services/github

И подключим их в основной модуль приложения.
Так-же подключим модули HttpClient [6] (для работы с http запросами) и ReactiveForms [7] (для работы с формами).

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { HttpClient } from '@angular/common/http';

import { AppComponent } from './app.component';
import { UserComponent } from './components/user/user.component';
import { ErrorComponent } from './components/error/error.component';
import { GithubService } from './services/github.service';

@NgModule({
  declarations: [AppComponent, UserComponent, ErrorComponent],
  imports: [BrowserModule, ReactiveFormsModule, HttpClient],
  providers: [GithubService],
  bootstrap: [AppComponent]
})
export class AppModule {}

Модели данных

Т.к. Angular использует Typescript [8], а Typescript дает нам типизацию, то хорошей практикой является описывать модели данных.
Это дает следующие плсы:
— удобный автокомплит при работе с приложением,
— проверка совпадения типов на стадии компиляции,
— дает другим разработчикам понять с какими данными они работают.

models/user.model.ts

export class User {
  login: string;
  id: number;
  node_id: string;
  avatar_url: string;
  gravatar_id: string;
  url: string;
  html_url: string;
  followers_url: string;
  following_url: string;
  gists_url: string;
  starred_url: string;
  subscriptions_url: string;
  organizations_url: string;
  repos_url: string;
  events_url: string;
  received_events_url: string;
  type: string;
  site_admin: boolean;
  name: string;
  company: string;
  blog: string;
  location: string;
  email: string;
  hireable: string;
  bio: string;
  public_repos: number;
  public_gists: number;
  followers: number;
  following: number;
  created_at: string;
  updated_at: string;
}

Сервис для получения данных

Работу с запросами на сервер в Angular принято выносить в сервисы [9].
В созданный ранее сервис добавим метод для получения данных пользователя.

services/github.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { User } from '../models/user.model';

@Injectable()
export class GithubService {

  // Подключаем модуль для работы с http
  constructor(private http: HttpClient) {}

  // Метод для запроса пользователя
  getUser(name: string): Observable<User> {
    const url = `https://api.github.com/users/${name}`;
    return this.http.get<User>(url);
  }
}

Поиск пользователя

В Angular из коробки встроен RxJs [10]. С помощью него и модуля работы с формами мы можем подписаться на изменение значения контрола, и получить данные пользователя.

app.component.html

<div class="container"
  [class.ready]="!!user">
  <input [formControl]="findControl"
    placeholder="GitHub username" />

  <app-user *ngIf="user"
    [user]="user"></app-user>

  <app-error *ngIf="error"></app-error>
</div>

app.component.ts

import { Component, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { GithubService } from './services/github.service';
import { User } from './models/user.model';
import { filter, switchMap, debounceTime, catchError } from 'rxjs/operators';
import { EMPTY } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  // Контрол для поиска пользователей
  findControl = new FormControl();
  // Ошибка поиска
  error: boolean = false;
  // Найденный пользователь
  user: User = null;

  // Подключение githubService для поиска пользователя
  constructor(private githubService: GithubService) {}

  // Хук инициализации компонента
  ngOnInit() {
    this.findControl.valueChanges
      .pipe(
        // Фильтруем если введено меньше двух символов
        filter(value => value.length > 2),
        // Ставим задержку одну секунду
        debounceTime(1000),
        // Запрашиваем данные пользователя
        switchMap(value =>
          this.githubService.getUser(value).pipe(
            // Обработка ошибок
            catchError(err => {
              this.user = null;
              this.error = true;
              return EMPTY;
            })
          )
        )
      )
      // Получение данных
      .subscribe(user => {
        this.user = user;
        this.error = false;
      });
  }
}

Остальные компоненты

Остальные компоненты являются «глупыми», т.е. не содержат в себе логики, а только отображают полученные данные.

user component

<div class="github-card user-card">
  <div class="header User"></div>
  <a class="avatar"
    [href]="'https://github.com/'+user.login">
      <img [src]="user.avatar_url+'&s=80'" [alt]="user.name" />
    </a>
  <div class="content">
    <h1>{{user.name}}</h1>
    <ul class="status">
      <li>
        <a [href]="'https://github.com/'+user.login+'?tab=repositories'">
            <strong>{{user.public_repos}}</strong>Repos
          </a>
      </li>
      <li>
        <a [href]="'https://gist.github.com/'+user.login">
            <strong>{{user.public_gists}}</strong>Gists
          </a>
      </li>
      <li>
        <a [href]="'https://github.com/'+user.login+'/followers'">
            <strong>{{user.followers}}</strong>Followers
          </a>
      </li>
    </ul>
  </div>
</div>

import { Component, Input, ChangeDetectionStrategy } from '@angular/core';
import { User } from '../../models/user.model';

@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class UserComponent {
  @Input()
  user: User;
}

error component

<div class="error">
  <h2>Oops!</h2>
  <b>
    User not found.
  </b>
  <p>Please try searching again.</p>
</div>

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

@Component({
  selector: 'app-error',
  templateUrl: './error.component.html',
  styleUrls: ['./error.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ErrorComponent {}

Плюсы использования Angular

— отделение получения данных от работы с ними,
— отделение шаблона от логики,
— четкая и понятная масштабируемая структура,
— встроенные модули для работы с формами и сервером,
— встроенный RxJs для ассинхронной работы,
— строгая типизация проверка на наличие ошибок при компиляции.

Исходный код

github [11]
live demo [12]

Выводы

Как было показано выше любое приложение (особенно небольшое) можно написать используя разные библиотеки, фреймворки или чистый JS [13].

Более важным является знание инструментов которые вы используете, и понимание на сколько они подходят в данной ситуации.

Всем успехов в изучении и чистого кода!

Автор: Климент

Источник [14]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/288992

Ссылки в тексте:

[1] Как сделать поиск пользователей по GitHub используя React + RxJS 6 + Recompose: https://habr.com/post/419559/

[2] Как сделать поиск пользователей по GitHub без React + RxJS 6 + Recompose: https://habr.com/post/419653/

[3] Как сделать поиск пользователей по Github используя VanillaJS: https://habr.com/post/419893/

[4] Angular: https://angular.io/

[5] angular CLI: https://cli.angular.io/

[6] HttpClient: https://angular.io/guide/http

[7] ReactiveForms: https://angular.io/guide/reactive-forms

[8] Typescript: http://www.typescriptlang.org/

[9] сервисы: https://angular.io/tutorial/toh-pt4

[10] RxJs: http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html

[11] github: https://github.com/klimentru1986/github-ui-angular

[12] live demo: https://stackblitz.com/github/klimentru1986/github-ui-angular

[13] чистый JS: http://vanilla-js.com/

[14] Источник: https://habr.com/post/419933/?utm_source=habrahabr&utm_medium=rss&utm_campaign=419933