Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

Angular 17 – Control Flow Syntax

Merhaba,

Bu içeriğimizde Angular 17 ile gelen ve built-in olarak mimaride varlık gösteren *ngIf, *ngFor ve *ngSwitch gibi direktifler yerine daha programatik bir üslupla if/else, for ve switch yapılarını kullanmamızı sağlayan Control Flow Syntax isimli özelliği inceliyor olacağız.

Öncelikle yukarıda bahsedilen direktiflerin yeni syntax’larına odaklanmadan önce bu güne kadar Angular’da nasıl çalıştıklarına göz atarak başlayalım.

Bizler bu güne kadar Angular mimarisinde built-in olarak gelen yapısal dediğimiz(Structural Directives) direktifler sayesinde herhangi bir html nesnesini sayfaya ekleyebiliyor, çıkarabiliyor yahut manipüle edebiliyorduk. Yani bu direktifler ile DOM nesnesinin yapısına müdahale edebiliyorduk. Misal olarak aşağıdaki kod bloğunu ele alırsak eğer;

    <div *ngIf="condition">
      <ul>
        <li *ngFor="let number of numbers">
          {{number}}
        </li>
      </ul>
    </div>

Görüldüğü üzere * karakteriyle başlayan *ngIf ve *ngFor gibi yapısal direktifler eşliğinde yürütülen bu çalışma esasında Angular compiler’ı tarafından bir JavaScript koduna dönüştürülmektedir. Tabi Angular JavaScript’i üretebilmek için öncelikle component’in template’ini aşağıdaki gibi parça parça view’lere ayırmakta;

    <div *ngIf="condition">

    </div>
      <ul>

      </ul>
        <li *ngFor="let number of numbers">
          
        </li>

ve böylece tüm bu parçaları esasında bir ng-template içerisinde * karakteri eşliğinde direktiflerle kullanmamızı sağlayarak syntactic sugar uygulamaktadır. Yani Angular compiler, yukarıdaki örneği arkaplanda aşağıdaki hale getirmektedir;

    <ng-template [ngIf]="condition">
    <div>
      <ng-template>
      <ul>
        <ng-template [ngFor]="numbers" let-number>
        <li>
          {{number}}
        </li>
        </ng-template>
      </ul>
      </ng-template>
    </div>
    </ng-template>

Burada esasında her bir view’in içeriği static bir yapıya sahiptir. Yani değişmez! Ancak burada dinamik olarak içeriklerin değişmesi, başka bir deyişle eklenmesi gerekmektedir. İşte tam bu noktada <!-- special comment --> devreye girmektedir.

Angular, bildiğiniz üzere içerisine alt view’leri ekleyip kaldırabileceğiniz ViewContainer kavramına sahiptir. Bu yapılanma sayesinde DOM’da gerekli dinamik tutumu sergileyebilmektedir ve yukarıda bahsi geçen içerik değişiklikleri bu container sayesinde yürütülmektedir. Angular, DOM’da içeriğin değişeceği dinamik nokta için container’ı konumlandırabilmek için özel bir html yorumu kullanmaktadır. Ve aslında şu ana kadar anlatılanlarda da işin özünde yapılanlar bundan ibarettir. Misal olarak; *ngIf arkaplanda bir ViewContainer oluşturacak ve bu container ise özel bir html yorumu ile ilgili noktayla ilişkilendirilecektir. Verilen koşula göre bu noktaya alt view eklenecek yahut çıkarılacaktır. Yani o nesne ya gösterilecek ya da kaldırılmış olacaktır.

Zaten hatırlarsanız eğer, bundan dolayı kendimize özel yapısal direktifleri(Custom Structural Directives) oluştururken de ViewContainerRef‘ten istifade etmekteyiz.

Uzun lafın kısası, bizler built-in gelen direktifler sayesinde arkaplanda farkında olmaksızın template’i önce ng-template‘e dönüştürmekte ve ardından da ViewContainer ile bunları dinamik bir şekilde yönetebilmekteyiz. Bu oldukça güçlü gözüken ama pekte sezgisel olmayan yapılanmanın ister istemez compiler açısından maliyet gibi dezavantajları da mevcuttur. Angular ekibi, bu duruma karşın direktifler yerine ek compiler yükü olmaksızın aynı işi yapacak ve aynı view’i oluşturacak daha performanslı olan Control Flow Syntax‘ı geliştirmişlerdir.

    @if(condition)
    {
      <div>
        <ul>
          @for(number of numbers;track $index){
            <li>{{number}}</li>
          }
        </ul>
      </div>
    }

İşte… Görüldüğü üzere Angular, artık direktiflere nazaran daha güçlü ve programatik üsluba daha uygun bir syntax ile bizlere eşlik edebilecektir.

Not : Artık bu syntax sayesinde @, { ve } karakterleri özel anlamlara sahip olacağından dolayı bu karakterlerin template içerisinde kullanılması hataya sebebiyet verecektir. Haliyle bunların kullanılabilmesi için aşağıdaki eşdeğerlerinin kullanılması gerekmektedir.
@ = \&#64;
{ = \&#123;
} = \&#125;

Şimdi gelin control flow syntax ile gelen tüm ifadeleri tek tek detaylıca inceleyelim.

if statement

En açık haliyle aşağıdaki gibi kullanılabilir;

    @if(condition == 1)
    {
      1
    }@else if(condition == 2)
    {
      2
    }@else{
      3
    }

Bunun dışında ekstradan tek bir detaya sahiptir, o da, kontrol edilmiş koşulun sonucunu da aşağıdaki gibi farklı bir değişkene atayabilirsiniz;

    @if(condition == 1; as result)
    {
      1
      {{result}}
    }

Yukarıdaki as result keyword’ü sayesinde condition == 1 koşulunun sonucu elde edilebilmektedir.

for statement

for ifadesinin kullanımı ise aşağıdaki gibi track keyword’ü ile birliktedir;

  <ul>
    @for(number of numbers;track number){
      <li>{{number}}</li>
    }
  </ul>

Evet, track keyword’ünün kullanımı zorunludur.

Şahsen for döngüsünde yapılan en yararlı eklemelerden biri boş koleksiyonların işlenebilmesidir. Şöyle ki;

  <ul>
    @for(number of numbers;track number){
      <li>{{number}}</li>
    }
    @empty{
      <li>
        <strong>No numbers</strong>
      </li>
    }
  </ul>

Önceden bu işlemi yapabilmek için önce *ngIf ile gerekli kontrolün yapılmasını ve eğer koleksiyon boş ise bir mesajın görüntülenmesini sağlamamız gerekiyordu. Yeni syntax’ta ise işler ne kadar kolay ve şık değil mi 🙂

Bu arada eskiden sahip olunan $index, $first, $last, $even, $odd ve $count gibi değişkenlere hala erişilebilmektedir.

    @for(number of numbers;track number;let f = $first; let l = $last){
      <li>{{number}} - {{f}} -- {{l}}</li>
    }

Unutmayın ki for döngüsü, yeni syntax’ında eskisine nazaran oldukça farklı ve etkili bir algoritmayla gelmiştir ve bundan dolayı daha performanslı ve hızlı çalışma sergilemektedir.

switch statement

switch yapısı da aşağıdaki syntax ile kullanılabilmektedir;

    @switch(number){
      @case(1)
      {
        <div>User</div>
      }
      @case(2){
        <div>Anonymous</div>
      }
      @default{
        <div>Other</div>
      }
    }

Mevcut Uygulamalardaki Direktifleri Yeni Syntax’a Dönüştürmek

Mevcut uygulamalarınızdaki direktifler ile yapılan operasyonları control flow syntax’a dönüştürmek istiyorsanız eğer bunu manuel yapabileceğiniz gibi Angular CLI’dan yardım alarakta gerçekleştirebilirsiniz.

Bunun için CLI’a vermeniz gereken talimat aşağıdakinden ibaret olacaktır.

ng g @angular/core:control-flow

Bu talimat neticesinde hem uygulamadaki component’ler de yapılan direktif çalışmaları yeni syntax’a geçirilecek hem de template’ler de bulunan @, { ve } gibi özel karakterler önceki satırlarda bahsedildiği üzere html varlıklarına dönüştürülecektir.

Nihai olarak;
Anlaşılan o ki, Angular ekibi gelecekte control flow syntax’a odaklanacak ve projelerde ihtiyaç noktalarında önerilen davranış olarak öne çıkaracaktır kanaatindeyim. Tabi bu durumda, control flow syntax’ın gelmesi demek structural directives’lerin kullanımdan kaldırılacağı anlamına gelmemektedir. Sevenler istediği taktirde direktiflerle yola devam edebilecektir 🙂

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Bunlar da hoşunuza gidebilir...

4 Cevaplar

  1. Doğukan Koç dedi ki:

    Teşekkürler hocam emeğinize sağlık faydalı bir içerik olmuş.

  2. Doğukan Koç dedi ki:

    Geçen hafta Angular Material kütüphanesinden bir component kullanmak istediğimde örnek kodlarda Control FLow Sytanx kullanılmıştı. Projeme eklediğimde bu hazır kodu

    Unexpected character “EOF” (Do you have an unescaped “{” in your template? Use “{{ ‘{‘ }}”) to escape it.)

    Bu şekilde bir hata almıştım, işin içinden çıkamadım, Control Flow Sytanx’tan vazgeçip Scructural directives kullandım. Hocamızın makalede bahsettiği gibi şimdi çözüm yolu yeşil alanla yazılmış not kısmı olabilir diye düşünüyorum.

  3. Mehmet Kelleli dedi ki:

    Razor engine gibi olmus mukemmelllll

Bir yanıt yazın

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