Avatar ·

Как передать параметры URL (query string) в HTTP-запрос в Angular?

Всем привет! Я новичок в Angular и TypeScript, и никак не могу разобраться с передачей параметров в GET-запросе. У меня есть сервис, который получает список пользователей с сервера. Обычный запрос без параметров работает отлично: ```typescript getUsers(): Observable { return this.http.get('/api/users'); } ``` Но теперь мне нужно добавить фильтрацию: например, передать параметры `page=1`, `limit=10` и `search=john`. Я пробовал просто добавить их в строку URL вручную: ```typescript getUsers(page: number, search: string): Observable { return this.http.get(`/api/users?page=${page}&limit=10&search=${search}`); } ``` Это работает, но выглядит как-то коряво. Во-первых, если параметров много, строка становится нечитаемой. Во-вторых, если какой-то параметр пустой (например, `search` не задан), в URL всё равно будет `&search=undefined`. В-третьих, нужно экранировать спецсимволы, и я не уверен, что мой способ это делает. Я слышал, что в Angular есть специальный объект `HttpParams`, но документация для меня слишком сложная. Подскажите, как правильно и красиво передавать query-параметры в Angular? Желательно с примерами кода на TypeScript. Заранее спасибо! <<>>

Использование HttpParams для чистых и безопасных запросов

В Angular есть встроенный механизм для работы с query-параметрами — класс HttpParams из пакета @angular/common/http. Он решает все ваши проблемы: автоматически экранирует спецсимволы, игнорирует пустые/null/undefined значения (если настроить), и делает код гораздо читаемее.

Вот как должен выглядеть ваш сервис:

import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';

interface User {
  id: number;
  name: string;
  email: string;
}

@Injectable({ providedIn: 'root' })
export class UserService {
  private apiUrl = '/api/users';

  constructor(private http: HttpClient) {}

  getUsers(page: number = 1, search: string = ''): Observable<User[]> {
    // Создаём объект HttpParams и добавляем параметры
    let params = new HttpParams()
      .set('page', page.toString())
      .set('limit', '10');

    // Добавляем search только если он не пустой
    if (search) {
      params = params.set('search', search);
    }

    // Передаём params как второй аргумент
    return this.http.get<User[]>(this.apiUrl, { params });
  }
}

Почему это лучше ручной сборки строки?

  • Автоматическое экранирование: если search содержит пробелы, амперсанды (&) или кириллицу, HttpParams сам закодирует их (например, "john doe" станет "john+doe", "тест" станет "%D1%82%D0%B5%D1%81%D1%82").
  • Чистота URL: пустые параметры не добавляются, если вы используете проверку if (search).
  • Гибкость: можно легко добавлять/удалять/изменять параметры.
  • Типизация: TypeScript подскажет, какие методы доступны у HttpParams.

Расширенный пример с несколькими параметрами

Часто параметры приходят из формы или другого объекта. Вот как можно обработать динамический набор параметров:

interface UserFilters {
  page?: number;
  limit?: number;
  search?: string;
  sortBy?: string;
  order?: 'asc' | 'desc';
}

getUsers(filters: UserFilters): Observable<User[]> {
  let params = new HttpParams();

  // Проходим по всем ключам объекта filters
  Object.entries(filters).forEach(([key, value]) => {
    if (value !== undefined && value !== null && value !== '') {
      params = params.set(key, String(value));
    }
  });

  return this.http.get<User[]>(this.apiUrl, { params });
}

// Использование:
this.userService.getUsers({
  page: 1,
  limit: 20,
  search: 'john',
  sortBy: 'name',
  order: 'asc'
}).subscribe(users => console.log(users));

Важные методы HttpParams

  • set(param, value) — устанавливает значение параметра (если параметр уже существует, перезаписывает его).
  • append(param, value) — добавляет ещё одно значение к существующему параметру (для массивов, например ?tag=angular&tag=typescript).
  • delete(param) — удаляет параметр.
  • toString() — возвращает строку запроса (например, ?page=1&limit=10&search=john).

Совет по иммутабельности

Обратите внимание: set() и append() не изменяют исходный объект, а возвращают новый. Поэтому мы используем let params = ... и переназначаем переменную. Это сделано для иммутабельности и предотвращения побочных эффектов.

Таким образом, используя HttpParams, вы получаете чистый, безопасный и легко поддерживаемый код. Это стандартный подход в Angular-приложениях.

<<>>

Альтернатива: использование объекта с параметрами напрямую

Если вам не нужна сложная логика фильтрации (например, все параметры обязательны), можно передать объект params прямо в опции запроса, не создавая экземпляр HttpParams. Angular сам преобразует обычный объект в параметры запроса:

getUsers(page: number, limit: number): Observable<User[]> {
  const params = {
    page: page.toString(),
    limit: limit.toString()
  };

  return this.http.get<User[]>(this.apiUrl, { params });
}

Этот способ короче, но имеет недостатки:

  • Нет автоматического экранирования — если значения содержат спецсимволы, их нужно экранировать вручную через encodeURIComponent().
  • Нет методов append и delete — для массивов параметров придётся писать свою логику.
  • Пустые значения всё равно попадут в URL, если их явно не отфильтровать.

Поэтому данный подход подходит только для простых случаев, когда параметры — это числа или короткие строки без спецсимволов. Для продакшн-кода рекомендую использовать HttpParams из первого ответа.