Takip et

Angular Router ile Query Parametrelerini Kullanma Rehberi

Angular Router ile Query Parametrelerini Kullanma Rehberi Angular uygulamalarında yönlendirme, kullanıcı deneyiminin temel taşlarından biridir.

Angular Router ile Query Parametrelerini Kullanma Rehberi

Angular uygulamalarında yönlendirme, kullanıcı deneyiminin temel taşlarından biridir. Uygulama içinde farklı görünümler arasında geçiş yapmamızı sağlayan Angular Router, sadece statik URL yollarını değil, aynı zamanda dinamik veri iletmek için de güçlü mekanizmalar sunar. Bu mekanizmalardan biri de “query parametreleri”dir. Query parametreleri, bir URL’nin sonuna eklenen ve genellikle anahtar-değer çiftlerinden oluşan veri parçacıklarıdır. Kullanıcıların bir sayfadaki filtreleme, sıralama, sayfalama gibi etkileşimlerini veya uygulamanın belirli bir durumunu URL üzerinden paylaşılabilir hale getirmek için vazgeçilmezdirler.

Bu makalede, Angular Router ile query parametrelerinin ne olduğunu, neden önemli olduklarını, nasıl okunup oluşturulduklarını ve yönetildiklerini ayrıntılı bir şekilde inceleyeceğiz. Ayrıca, yaygın kullanım senaryolarını ele alacak, kod örnekleri sunacak ve en iyi pratikler hakkında ipuçları vereceğiz.

Query Parametreleri Nedir ve Neden Kullanılır?

Query parametreleri, bir URL’nin sorgu dizgesi (query string) bölümünde yer alan ve genellikle ? karakterinden sonra başlayan anahtar-değer çiftleridir. Örneğin, https://example.com/urunler?kategori=elektronik&sirala=fiyat-artana URL’sinde kategori=elektronik ve sirala=fiyat-artana birer query parametresidir.

Path parametrelerinden (örn: urunler/:id) farklı olarak, query parametreleri bir kaynağın belirli bir örneğini tanımlamak yerine, genellikle o kaynağın bir alt kümesini veya görünümünü değiştirmek için kullanılır.

Query Parametrelerinin Kullanım Alanları:

* Filtreleme: Bir ürün listesini kategoriye, fiyata veya markaya göre filtrelemek. (örn: urunler?kategori=kitap)
* Sıralama: Arama sonuçlarını fiyata, tarihe veya popülerliğe göre sıralamak. (örn: urunler?sirala=fiyat-azalana)
* Sayfalama (Pagination): Büyük veri kümelerini sayfalara ayırmak ve belirli bir sayfaya gitmek. (örn: urunler?sayfa=2&limit=10)
* Arama: Kullanıcının girdiği arama terimini URL’de taşımak. (örn: urunler?arama=laptop)
* Durum Paylaşımı: Bir uygulamanın belirli bir durumunu (örn: açık bir modal, seçili bir sekme) URL üzerinden paylaşılabilir hale getirmek.
* Analiz ve Takip: Pazarlama kampanyalarını veya kullanıcı davranışlarını takip etmek için UTM parametreleri gibi özel parametreler kullanmak.

Query parametreleri, bir uygulamanın durumunu URL’ye yansıtarak, kullanıcıların tarayıcılarının geri/ileri düğmelerini kullanmalarına olanak tanır, belirli bir durumu kolayca paylaşmalarını sağlar ve sayfa yenilemelerinde durumun kaybolmasını engeller.

Angular Router ile Query Parametrelerini Okuma

Angular uygulamalarında, aktif rotanın query parametrelerine erişmek için ActivatedRoute servisini kullanırız. Bu servis, mevcut rotanın URL’sini, parametrelerini ve diğer verilerini içeren bir dizi gözlemlenebilir (Observable) ve anlık görüntü (snapshot) özelliği sunar.

ActivatedRoute Servisi ve Query Parametreleri

ActivatedRoute servisini bir bileşenin constructor’ına enjekte ederek kullanmaya başlayabiliriz:

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

@Component({
  selector: 'app-product-list',
  templateUrl: './product-list.component.html',
  styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements OnInit {
  category: string | null = null;
  sortBy: string | null = null;

  constructor(private route: ActivatedRoute) { }

  ngOnInit(): void {
    // Query parametrelerini okuma
  }
}

Query parametrelerini okumanın iki ana yolu vardır: snapshot ve queryParams Observable’ı.

Snapshot ile Query Parametrelerini Okuma

ActivatedRoute.snapshot.queryParams özelliği, bileşen yüklendiğinde mevcut query parametrelerinin anlık bir görüntüsünü sağlar. Bu yöntem, parametrelerin bileşen yüklendikten sonra değişmeyeceği durumlarda veya sadece başlangıç değerlerini almak istediğinizde kullanışlıdır.

// ... ProductListComponent içinde

ngOnInit(): void {
  this.category = this.route.snapshot.queryParams['kategori'];
  this.sortBy = this.route.snapshot.queryParams['sirala'];

  console.log('Kategori (Snapshot):', this.category);
  console.log('Sıralama (Snapshot):', this.sortBy);
}

Dikkat: Eğer aynı bileşen içinde (örneğin, bir ürün listesi sayfasında farklı filtreler seçildiğinde) query parametreleri değişirse, snapshot yeni değerleri yansıtmayacaktır. Bu gibi dinamik senaryolar için queryParams Observable’ını kullanmak gerekir.

queryParams Observable ile Query Parametrelerini Okuma

ActivatedRoute.queryParams bir Observable’dır ve query parametrelerinde herhangi bir değişiklik olduğunda yeni değerleri yayar. Bu, aynı bileşen içinde kalırken URL’deki query parametrelerinin değiştiği senaryolar için idealdir. Örneğin, bir arama sayfasında farklı aramalar yapıldığında veya filtreler değiştirildiğinde bileşenin güncel kalmasını sağlar.

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-product-list',
  templateUrl: './product-list.component.html',
  styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements OnInit, OnDestroy {
  category: string | null = null;
  sortBy: string | null = null;
  private queryParamsSubscription: Subscription | undefined;

  constructor(private route: ActivatedRoute) { }

  ngOnInit(): void {
    this.queryParamsSubscription = this.route.queryParams.subscribe(params => {
      this.category = params['kategori'] || 'tümü'; // Varsayılan değer atama
      this.sortBy = params['sirala'] || 'varsayılan'; // Varsayılan değer atama
      console.log('Kategori (Observable):', this.category);
      console.log('Sıralama (Observable):', this.sortBy);
      // Parametreler değiştiğinde verileri yeniden yükleme veya filtreleme işlemleri burada yapılabilir.
      this.loadProducts();
    });
  }

  loadProducts(): void {
    console.log(Ürünler yükleniyor: Kategori=${this.category}, Sıralama=${this.sortBy});
    // API çağrısı veya filtreleme mantığı burada yer alacaktır.
  }

  ngOnDestroy(): void {
    // Bellek sızıntılarını önlemek için aboneliği iptal etmeyi unutmayın.
    if (this.queryParamsSubscription) {
      this.queryParamsSubscription.unsubscribe();
    }
  }
}

Bu örnekte, ngOnInit içinde queryParams Observable’ına abone oluyoruz. Her parametre değişikliğinde aboneliğin içindeki kod çalışacak ve bileşenimizin durumu güncellenecektir. ngOnDestroy yaşam döngüsü kancasında aboneliği iptal etmek, bellek sızıntılarını önlemek için kritik öneme sahiptir.

Angular Router ile Query Parametrelerini Yönlendirme

Query parametrelerini okumak kadar, onları oluşturup URL’ye eklemek de önemlidir. Angular Router, bu işlemi hem deklaratif (template içinde routerLink ile) hem de programatik (TypeScript kodunda Router servisi ile) olarak kolaylaştırır.

routerLink Direktifi ile Query Parametreleri Ekleme

routerLink direktifi, HTML şablonlarında navigasyon bağlantıları oluşturmak için kullanılır. Query parametrelerini eklemek için [queryParams] input’unu kullanırız. Bu input, anahtar-değer çiftlerini içeren bir JavaScript nesnesi alır.


Ürün Kategorileri

Şu anki Kategori: {{ category }}

Şu anki Sıralama: {{ sortBy }}

Bu örnekte, farklı kategorilere ve sıralama seçeneklerine sahip bağlantılar oluşturduk. Her bağlantıya tıklandığında, /urunler rotasına ilgili query parametreleri eklenerek navigasyon gerçekleştirilir.

queryParamsHandling ile Query Parametrelerini Yönetme

routerLink veya router.navigate() ile query parametreleri eklerken, mevcut query parametrelerinin nasıl ele alınacağını belirlemek için queryParamsHandling özelliğini kullanabiliriz. Bu özellik üç farklı değere sahiptir:

* 'merge': Yeni query parametrelerini mevcut olanlarla birleştirir. Aynı anahtara sahip parametreler varsa, yenisi eskisinin üzerine yazar. Bu, en yaygın ve genellikle istenen davranıştır.
* 'preserve': Mevcut query parametrelerini aynen korur ve yeni eklenen parametreleri göz ardı eder. Yeni bir query parametresi eklemek yerine, sadece rotanın path’ini değiştirmek istediğinizde kullanışlıdır.
* undefined veya null (varsayılan): Mevcut query parametrelerini tamamen kaldırır ve sadece yeni belirtilen parametreleri kullanır. Eğer queryParams belirtilmemişse, URL’deki tüm query parametreleri silinir.

Örnekler:



Fiyata Göre Sırala



Sadece Rota Değiştir



Tüm Filtreleri Temizle



Sayfa 1'e Git

'merge' genellikle filtreleme, sıralama ve sayfalama gibi işlemlerde en kullanışlı olanıdır, çünkü kullanıcının mevcut durumunu korurken yeni bir parametre eklemesine veya değiştirmesine olanak tanır.

Programatik Navigasyon ile Query Parametreleri Ekleme

Bazen bir butona tıklandığında, bir form gönderildiğinde veya bir servisten veri geldiğinde programatik olarak navigasyon yapmak gerekebilir. Bu durumlarda Router servisini kullanırız.

import { Component } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-search-bar',
  template: 
    
    
    
  
})
export class SearchBarComponent {
  searchTerm: string = '';

  constructor(private router: Router, private route: ActivatedRoute) { }

  search(): void {
    this.router.navigate(
      ['/urunler'],
      {
        queryParams: { arama: this.searchTerm },
        queryParamsHandling: 'merge' // Mevcut parametreleri koruyarak arama terimini ekle
      }
    );
  }

  clearFilters(): void {
    this.router.navigate(
      ['/urunler'],
      {
        queryParams: {}, // Tüm query parametrelerini temizle
        queryParamsHandling: '' // Varsayılan davranış (queryParamsHandling: 'merge' ile aynı değil, mevcutları sıfırlar)
      }
    );
    // Alternatif olarak, queryParams: null da kullanılabilir, bu da tüm parametreleri siler.
    // this.router.navigate(['/urunler'], { queryParams: null });
  }

  // Sayfalama örneği
  goToPage(pageNumber: number): void {
    this.router.navigate(
      [], // Mevcut rotada kalmak için boş dizi
      {
        relativeTo: this.route, // Mevcut rotaya göre navigasyon yap
        queryParams: { sayfa: pageNumber },
        queryParamsHandling: 'merge' // Mevcut parametreleri koruyarak sayfa numarasını güncelle
      }
    );
  }
}

router.navigate() metodunun ikinci argümanı bir navigasyon konfigürasyon nesnesidir. Bu nesne içinde queryParams ile parametreleri ve queryParamsHandling ile davranışını belirtebiliriz. relativeTo: this.route kullanımı, mevcut rotanın URL’sini temel alarak navigasyon yapmayı sağlar, bu da özellikle aynı bileşen içinde kalırken sadece query parametrelerini değiştirmek istediğimizde kullanışlıdır.

Query Parametrelerini Yönetme ve Güncelleme

Uygulama geliştikçe, query parametrelerini dinamik olarak eklemek, güncellemek veya kaldırmak gerekebilir. Bu, kullanıcı etkileşimlerine veya uygulamanın iç mantığına bağlı olarak değişebilir.

Parametre Ekleme veya Güncelleme

queryParamsHandling: 'merge' kullanmak, mevcut parametreleri koruyarak yeni parametreler eklemenin veya var olanları güncellemenin en yaygın yoludur.

// Bir filtre ekleme veya mevcut bir filtreyi güncelleme
updateFilter(filterName: string, filterValue: string): void {
  this.router.navigate(
    [], // Mevcut rotada kal
    {
      relativeTo: this.route,
      queryParams: { [filterName]: filterValue },
      queryParamsHandling: 'merge' // Mevcut parametrelerle birleştir
    }
  );
}

// Birden fazla parametreyi aynı anda güncelleme
applyMultipleFilters(category: string, minPrice: number): void {
  this.router.navigate(
    [],
    {
      relativeTo: this.route,
      queryParams: { kategori: category, minFiyat: minPrice },
      queryParamsHandling: 'merge'
    }
  );
}

Parametre Silme

Bir query parametresini URL’den kaldırmak için, o parametrenin değerini undefined veya null olarak ayarlayabilir ve yine queryParamsHandling: 'merge' kullanabiliriz. Router, undefined veya null değere sahip parametreleri URL’ye eklemeyecektir.

// Belirli bir filtreyi kaldırma
removeFilter(filterName: string): void {
  const currentQueryParams = { ...this.route.snapshot.queryParams }; // Mevcut parametreleri kopyala
  delete currentQueryParams[filterName]; // Kaldırılacak parametreyi sil

  this.router.navigate(
    [],
    {
      relativeTo: this.route,
      queryParams: currentQueryParams, // Güncellenmiş parametreleri gönder
      queryParamsHandling: 'merge' // Bu durumda aslında 'merge' gerekli değil ama alışkanlık olarak kullanılabilir
    }
  );
  // Daha basit bir yol:
  // this.router.navigate(
  //   [],
  //   {
  //     relativeTo: this.route,
  //     queryParams: { [filterName]: null }, // Parametreyi null olarak ayarla
  //     queryParamsHandling: 'merge'
  //   }
  // );
}

// Tüm filtreleri temizleme
clearAllFilters(): void {
  this.router.navigate(
    [],
    {
      relativeTo: this.route,
      queryParams: null // Tüm query parametrelerini kaldır
    }
  );
}

queryParams: null kullanmak, mevcut rotadaki tüm query parametrelerini temizlemenin en doğrudan yoludur.

Gelişmiş Kullanım Senaryoları ve İpuçları

Query parametrelerini etkin bir şekilde kullanmak için bazı gelişmiş teknikler ve en iyi pratikler mevcuttur.

Type Safety (Tip Güvenliği) ile Query Parametreleri

Query parametreleri varsayılan olarak string türündedir ve ActivatedRoute.queryParams bir Params (anahtar-değer çiftleri için) nesnesi döndürür. Bu, parametreleri okurken veya yazarken tip hatalarına yol açabilir. Tip güvenliğini artırmak için bir interface tanımlayabiliriz:

// query-params.interface.ts
export interface ProductQueryParams {
  kategori?: string;
  sirala?: 'fiyat-artana' | 'fiyat-azalana' | 'yeni' | 'populer';
  arama?: string;
  sayfa?: number;
  limit?: number;
  [key: string]: any; // Diğer dinamik parametreler için
}

// product-list.component.ts
import { ProductQueryParams } from './query-params.interface';

// ...
export class ProductListComponent implements OnInit, OnDestroy {
  currentParams: ProductQueryParams = {};
  // ...

  ngOnInit(): void {
    this.queryParamsSubscription = this.route.queryParams.subscribe((params: ProductQueryParams) => {
      this.currentParams = params;
      this.category = params.kategori || null;
      this.sortBy = params.sirala || null;
      // ...
    });
  }

  updateCategory(category: string): void {
    this.router.navigate([], {
      relativeTo: this.route,
      queryParams: { kategori: category } as ProductQueryParams, // Tip dönüşümü
      queryParamsHandling: 'merge'
    });
  }
}

Bu yaklaşım, parametre adlarının ve olası değerlerinin tutarlı kalmasına yardımcı olur.

URL Temizliği ve Varsayılan Değerler

Varsayılan değerlere sahip parametreleri URL’de göstermek, URL’yi gereksiz yere uzatabilir ve okunabilirliğini azaltabilir. Örneğin, sayfa=1 varsayılan sayfa numarası ise, bunu URL’de göstermek genellikle gereksizdir.

Bir parametrenin değeri varsayılan ise, onu URL’den kaldırarak URL’yi temiz tutabiliriz:

// Programatik navigasyon sırasında
navigateToProducts(category: string | null, page: number = 1): void {
  const queryParams: ProductQueryParams = {};

  if (category) {
    queryParams.kategori = category;
  }
  if (page > 1) { // Sadece 1'den büyük sayfa numaralarını URL'ye ekle
    queryParams.sayfa = page;
  }

  this.router.navigate(['/urunler'], {
    queryParams: queryParams,
    queryParamsHandling: 'merge'
  });
}

Bu yaklaşım, sadece varsayılan olmayan veya anlamlı olan parametrelerin URL’de görünmesini sağlar.

SEO ve Paylaşılabilirlik Üzerindeki Etkisi

Query parametreleri, bir sayfanın içeriğini veya görünümünü değiştirdiğinde, SEO açısından dikkatli olunması gerekir. Arama motorları, farklı query parametrelerine sahip URL’leri farklı sayfalar olarak algılayabilir ve bu da yinelenen içerik sorunlarına yol açabilir.

* Canonical URL’ler: rel="canonical" etiketini kullanarak arama motorlarına bir sayfanın “tercih edilen” veya “ana” URL’sini belirtebilirsiniz. Bu, özellikle filtreleme ve sıralama gibi işlemlerle çok sayıda benzer URL oluştuğunda önemlidir.
* Anlamlı Parametreler: Parametre adlarını ve değerlerini açıklayıcı tutun (kategori=kitap yerine cat=k gibi kısaltmalardan kaçının).
* Paylaşılabilirlik: Query parametreleri sayesinde kullanıcılar, belirli bir filtre veya arama sonucuna sahip bir sayfanın URL’sini kolayca paylaşabilirler. Bu, kullanıcı deneyimi için büyük bir artıdır.

State Management ile Entegrasyon

Büyük ölçekli Angular uygulamalarında, global state yönetimi (NgRx, Akita, NGRX Component Store vb.) kullanmak yaygındır. Query parametrelerini global state ile senkronize etmek, uygulamanın durumunu kalıcı ve paylaşılabilir hale getirmek için güçlü bir yöntemdir.

* URL -> State: ActivatedRoute.queryParams Observable’ına abone olarak, URL’den gelen parametreleri state’e dispatch edebilirsiniz.
* State -> URL: State’teki değişiklikleri dinleyerek, Router servisi aracılığıyla URL’deki query parametrelerini güncelleyebilirsiniz.

Bu iki yönlü senkronizasyon, uygulamanın durumunun her zaman URL ile eşleşmesini sağlar.

Hata Yönetimi ve Varsayılan Değerler

Query parametreleri isteğe bağlıdır ve her zaman mevcut olmayabilir. Bu nedenle, bileşenlerinizde parametreleri okurken null veya undefined durumlarını ele almak önemlidir. Yukarıdaki örneklerde gösterildiği gibi, params['kategori'] || 'tümü' gibi varsayılan değer atamaları bu konuda yardımcı olur. Ayrıca, parametrelerin beklenen formatta (örn. bir sayfa numarasının sayı olması) olup olmadığını kontrol etmek için doğrulama yapmak da iyi bir pratiktir.

this.queryParamsSubscription = this.route.queryParams.subscribe(params => {
  this.category = params['kategori'] || 'tümü';
  const pageParam = parseInt(params['sayfa'] as string, 10); // String'i sayıya dönüştür
  this.page = !isNaN(pageParam) && pageParam > 0 ? pageParam : 1; // Geçerli sayı değilse veya 0'dan küçükse 1 yap
  // ...
});

Sık Yapılan Hatalar ve Çözümleri

Angular Router ile query parametrelerini kullanırken karşılaşılan bazı yaygın hatalar ve bunların nasıl çözüleceği:

* snapshot yerine queryParams Observable kullanmama: Aynı bileşen içinde query parametreleri değiştiğinde bileşenin güncellenmemesi.
* Çözüm: Dinamik olarak değişen parametreler için her zaman ActivatedRoute.queryParams Observable’ına abone olun ve ngOnDestroy içinde aboneliği iptal etmeyi unutmayın.
* queryParamsHandling‘i yanlış anlama: Özellikle 'merge' ve varsayılan davranış arasındaki farkı karıştırmak. Varsayılan davranış (null veya undefined olarak bırakmak), mevcut query parametrelerini temizler. 'merge' ise mevcutlarla birleştirir.
* Çözüm: Her navigasyon işleminde queryParamsHandling‘in istenen davranışı sağladığından emin olun. Genellikle merge kullanmak istenir.
* URL’de gereksiz parametre birikimi: Varsayılan değerdeki parametrelerin veya artık kullanılmayan parametrelerin URL’de kalması.
* Çözüm: Programatik navigasyon yaparken, yalnızca anlamlı ve varsayılan olmayan parametreleri queryParams nesnesine ekleyin. Parametreleri kaldırmak için değerlerini null veya undefined olarak ayarlayabilir veya queryParams: null ile tümünü temizleyebilirsiniz.
* Tip güvenliği eksikliği: Query parametrelerinin her zaman string olarak gelmesi ve sayısal veya boolean değerlere dönüştürülürken hata yapılması.
* Çözüm: Parametreleri okurken uygun tip dönüşümlerini (parseInt, parseFloat, JSON.parse) uygulayın ve isNaN gibi kontrollerle geçerliliğini doğrulayın. Ayrıca, yukarıda bahsedilen interface kullanımı ile tip güvenliğini artırın.
* Abonelikleri iptal etmeyi unutma: queryParams Observable’ına abone olunduğunda, bileşen yok edildiğinde aboneliğin iptal edilmemesi bellek sızıntılarına yol açar.
* Çözüm: Her zaman ngOnDestroy yaşam döngüsü kancasında subscription.unsubscribe() metodunu çağırarak abonelikleri temizleyin. takeUntil operatörünü kullanmak da yaygın bir RxJS çözümüdür.

Sonuç

Angular Router ile query parametrelerini kullanmak, dinamik ve kullanıcı dostu web uygulamaları oluşturmanın temel bir parçasıdır. Filtreleme, sıralama, sayfalama ve uygulama durumu paylaşımı gibi birçok senaryoda vazgeçilmez bir araçtır. ActivatedRoute servisi ile parametreleri okumak ve Router servisi veya routerLink direktifi ile parametreleri oluşturup yönetmek, Angular’ın güçlü yönlerinden biridir.

Bu makalede ele aldığımız konular ve kod örnekleri sayesinde, Angular uygulamalarınızda query parametrelerini etkili bir şekilde kullanmak için sağlam bir temel oluşturduğunuzu umuyoruz. En iyi pratikleri (tip güvenliği, URL temizliği, abonelik yönetimi) uygulayarak, hem geliştirici deneyiminizi iyileştirecek hem de son kullanıcılar için daha sağlam ve sezgisel uygulamalar sunacaksınız. Unutmayın, iyi tasarlanmış URL’ler, uygulamanızın kullanılabilirliğini ve paylaşılabilirliğini önemli ölçüde artırır.

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.