[Çeviri] Angular’da, Decorator Aracılığı İle Router Verisine Ulaşmak.

Tahir KARDAK
5 min readJul 17, 2021

--

Bu makale Georgii Kuzmin tarafından yazılan “Router’s data with the decorator in Angular” makalesinin Türkçe çevirisidir. Makaleyi orijinal dilinde okumak için aşağıdaki linki tıklayabilirsiniz.

Başlıyoruz….

Componentlere çözümlenmiş verileri hemen dahil edin.

Bir Angular geliştiricisi olarak, Router’da verileri component yüklenmeden çözümlemek isterim. Bu durum, veriler yüklenirken ekranın yanıp sönmesi veya iskelet yüklemesi olmaksızın, component’i daha kararlı yapmaktadır. Kullanıcılar sayfa yüklendiğinde sayfa ile veriyi aynı anda görmek ister. İşte bu yüzden Angular ekibi Router Resolver’ı icat ettiler.

☹️ Problem.

Mevcutta Routerdan gelen verilere ulaşmak için ActivatedRoute veya ActivatedRouteSnapshot inject etmek zorundayım.

Dahası, Eğer URL de dinamik değişen Id’ler mevcut ise Angular, Route Component’i tekrardan yüklemiyor. Angular dinamik değişen url’leri önceki route aynı olduğunu düşünüyor (library/1 = library/2). Çünkü Angular kaputun altında routerları karşılaştırırken, basit object referans karşılaştırması kullanıyor. Angular’a bu işlemi bir işaret yada RouteReuseStrategy sınıfı derleme yaklaşımı ile yeniden yapmamasını söyleyebilirsiniz.

Yani, dinamik olarak değişen bir route’niz varsa ve dinamik kısım değiştikçe yeni veriyi çözümlemek için ActivatedRoute kullanmak ve veri alanlarına ulaşmak için subscribe olmalısınız.

Frontend Meetup’larında konuşmacılara, componentin içinde garip injectionlar ve subscriptler olmadan verilere ulaşmak için bir çözüm bulup bulmadıklarını sıklıkla sorarım. Görünen o ki kimse bu konu hakkında düşünmemiş bile. Angular Ekibi, Veriyi çözümlemek için Input gibi bir decorator de sunmuyor.

İhtiyacım olan veriyi çözümlemek için ActivatedRoute inject edip, ona subscribe olmak ve pipe işlemleri yapmak istemiyorum.

Bunun yerine şöyle bir şey istiyorum:

Güzel değil mi?

😎 Çözüm.

Buradaki fikir; Router Context içerisinden mevcut route bulmak, router outlet’i almak, ve component’in içinde ona subscribe olmak, bir getter yardımı ile en güncel verileri subscription’dan döneceğiz. Ancak Decorator kullanılan component destroy olmayacak bu yüzden Router outlet’te yapılan subscription işlemini canlı tutamayacağız. Bu yüzden Angular her seferinde componenti tekrar derlediğinden, Bizim decorator, doğru olan veriyi dönmek yerine ilk router outletteki veriyi dönecektir.

Bazı fonksiyonlar yazalım!

Öncelikle; Decoratorler henüz Angular ortamlarında olmadığı için Angular DI Container’ına erişmemizi sağlayacak, inject edilebilen bir statik değişkene (bir önceki yazımda bahsetmiştim. )ihtiyacımız var. Ancak, bunlara ait servis ve inject edilebilir özelliklerini kullanmak zorundayız. Mevcutta hangi route’in aktif olduğunu anlama için en az bir tane Router’a ve Router’daki verileri çözülerken, Component’teki değişiklikleri tespit etmek için ChangeDetectorRef ihtiyacımız var.

source

Aşağıda görebileceğiniz gibi, StaticInjectorService’mizi modül’ün içinde sunuyoruz (8. satır). Bu işlem servisin Instance’nı oluşturmak ve servisin Constructor’ını calıştırmak için yapılmıştır.

Source

Şimdi Decorator’ümüzü geliştirmek için her şeye sahibiz!

Bir kaç değişken tanımlayalım ve neden bu değişkenleri ihtiyacımız var satır satır anlamaya çalışalım

Source

Bir önceki makalemde; Typescripte decorator’lerin nasıl calıştığını açıklamıştım. Herkesin bu konuyu bildiğini düşünüp, bu kısmı geçelim.

İhtiyaçlarımız:

— Route’mizi bulmak için bir adet router (7. satır).

— Subject tipindeki trigger (8. satır) bize subscription’ı tekrardan çalışması ve router verilerini dönmek için yardımcı olacak tanımlandı . Nasıl uygulanacağını ilerde göreceğiz.

— Destroy subject(9. satır) ise trigger ‘in yaptığı işin tam tersini yapacak. Component’in işi bittiğinde(destroy) unsubscribe işlemi yapacak.

— Router, route context’indeki değişikleri tutar. Bu yüzden any tipine cast etmeliyiz ve İhtiyacımız olan hilemizi yapabilelim(10. satır).

— Router verilerini tekrar kullanmak için routerData değişkenini tanımlıyoruz(15. satır).

— ChangeDetectorRef’i ilerde kullanmak için tanımlanıyoruz(16. satır).

— Boolean inited değişken ise component oluşturulduğunda false işaretlemek için tanımlandı(16. satır). Dosyada bunu değişinin kullanımını göreceğiz.

— Component’in referansını tutmak ve değişiklikleri yakalayıp, fonksiyonumuza bağlamak için

Bildiğiniz gibi Subject tipinde triggerdeğişkenini tanımlamıştık. Amacı, Decorator’ün kullanıdığı değişkenden bir değer alındığında; Boş(EMPTY) bir emisyon yayarak Component’in yaratılışı hakkında bilgi vermektir. Bu sayede component’in ne zaman yaratığını biliyoruz ve router’in instancesini alarak sihrimizi gerçekleştirip değerimizi alabileceğiz.

source

Basit bir fonksiyon ile contextMapt’en o an aktif olan outlet bilgisini arıyoruz (4. satır).

source

Daha sonra outlet’ten component’in referansını alıyoruz ve ihtiyacımız olan verilerle sırayla bir router arıyoruz(13. satır).

source

Component’imize bağılı olan bir değişik takip(change detector) referansı almalıyız(2. satır). Data sonra onDestroy metodunu register edelim. Bu kısımda inated değişkeni false set edip boş bir değer yayarak, router verisinden unsubscribe oluyoruz(11. satır). En son olarak verinin içinden name || key bilgisini dönüyoruz.

source

Subscribe callback fonksiyonunda, aradığımız çöüzmlenmiş verileri alıyoruz ve Hedef sınıftaki değişken bilgisine atıyoruz. Sonrasında component’i markForCheck kullanarak dirty olarak işaretliyoruz.

source

Decorator’ümüz, kullanıldığı alan için getter ve setter’i içeren bir tanımlayıcı döner.

source

Getter’in içersinde inited değişkenini true olarak değiştiriyoruz. Eğer bu değişken false ise, triggerdeğişkenini bilgilendirmek için boş bir değer emit edecek. Sonrasında orijinal getter çalıştırarak routerdaki verileri dönüyoruz.

Decorator’e ait tüm kod şu şekilde.

source

Basitçe aşağıdaki şekilde kullanın,

source

Data değişkeni için Router’daki bilgi şu şekilde.

source

Angular ekibi neden buna benzer bir çözüm sunmuyor bilmiyorum. Benim bakış acıma göre, bu yöntem daha açıklayıcı ve sürekli olarak subscription’ları yönetmeye göre, kullanımı daha kolay. Bu decorator yönetiminin bazı sorunlara neden olabileceği durumlar olduğuna da inanıyorum.

Tüm koda, repository’imden ulaşabilirsiniz.

Kullanımına da buradan bakabilirsiniz.

Alena Rotaru ✈ and Ivan Radchenko’ye teşekküler.

--

--