Как стать автором
Обновить

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

Время на прочтение5 мин
Количество просмотров5.5K
image

Эта статья является ответом на:


Целью статьи является:

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

Целью статьи НЕ является:

  • разжигание очередного холивара.

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

Подготовка


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

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 (для работы с http запросами) и ReactiveForms (для работы с формами).

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, а 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 принято выносить в сервисы.

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

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. С помощью него и модуля работы с формами мы можем подписаться на изменение значения контрола, и получить данные пользователя.

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
live demo

Выводы


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

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

Всем успехов в изучении и чистого кода!
Теги:
Хабы:
Всего голосов 24: ↑19 и ↓5+14
Комментарии28

Публикации

Истории

Работа

Ближайшие события

7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
22 – 24 ноября
Хакатон «AgroCode Hack Genetics'24»
Онлайн
28 ноября
Конференция «TechRec: ITHR CAMPUS»
МоскваОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань