Angular 1.x Sonrası ve Angular 2

25 Oca

Google tarafından geliştirilen AngularJS geliştirme çatısında AngularJS 1.x ve Angular2 şeklinde bir ayrıma gidildi. Bu ayrım yaklaşık iki sene önce başladı ve bugün sonuçlarını değerlendirme fırsatım oldu.

Stack Overflow tarafından 2015-2016 yılında ölçülen ve 50.000 geliştiricinin katıldığı anket sonuçlarına göre ortaya çıkan teknoloji eğilimleri aşağıdaki grafikteki gibidir. Bu anket sonucunu paylaşmamın sebebi, geliştiricisi olduğum bir javascript kütüphanesi olan Angularjs tarafında yaşanan gelişmelerin sonucunu yansıtabilmektir.

Stack Overflow Trending Tech Anketi
Stack Overflow Trending Tech Anketi

 

Bu sonuçlara göre Facebook şirketi tarafından geliştirilen React kütüphanesinin son yıllarda önemli oranda bir geliştiriciyi kendine çektiği görülmektedir. Buna rağmen Google tarafından geliştirilen Angularjs kütüphanesi epeyce gerilemiş durumda.

react-angularjs-trends
Angularjs ve React Google arama trendleri

 

Google trendleri göz önüne alındığında son zamanlarda Angularjs ve React arama oranlarında yine React kütüphanesine olan ilginin arttığı görülmektedir.

Angularjs gibi kullanışlı bir kütüphaneye olan ilginin bu kadar gerilemesinin nedenlerinden biri Angular 2 sürümüyle yeni bir yola girmesidir. Şüphesiz daha performanslı ve daha hafif bir ürün ortaya koymak amacıyla Google tarafından böyle bir adım atılmıştır. Hem TypeScript dilinin hem ECMAscript 6 dilinin gücünden faydalanılmıştır. Ancak Angular 2 sürümü, geliştiricilere TypeScript dilini de bilmeyi zorunlu kılan bir ortam sunmuştur. Yani saf javascript bilgisi ile Angular 2 geliştirme yapılamamaktadır. Oysa Angularjs 1.x sürümlerinde saf javascript bilgisi yeterlidir.

Angular 2 sürümünün kullanıcılar tarafından sıcak bir şekilde karşılanmamasının bir diğer neden de geriye dönük uyumluluğunun olmamasıdır. Bu durum, geliştiricileri bir yol ayrımına getirmiştir. Angularjs 1.x ile geliştirilmiş uygulamalarınızı korumak ve devam etmek mi, yoksa geriye dönük olarak tüm uygulamalarınızı Angular 2 ile yeniden yazmak mı? Bu durum, Angular desteği sunan geliştirici topluluklarını da ikiye bölmüş durumdadır. Bu durumun sonucu zamana bağlı olarak görülecektir.

Şüphesiz teknolojik evrimin büyük bir hızla yaşandığı yıllardayız. Belkide bir kaç sene sonra Angular ve React kütüphenelerinin pabucunu dama atacak ve yerlerine yeni kütüphaneler üretilecektir. Hani bir zamanlar frontend geliştirme tarafında  popüler olan Flash, Java Flex, Silverlight’ta olduğu gibi. Bu elbette kaçınılmaz bir gelişim sürecidir. Ancak şirketlerin kendi ürünlerini kullananlarının önüne engel çıkarmasına şahsen bir anlam verebilmiş değilim. Bu da benim kişisel görüşümdür.

Angularjs Emit ve Broadcast

7 Oca

Angularjs uygulamalarında Dom elemanlarını haberdar etmek için kullanılan iki yöntemden biri broadcast diğeri de emit metotlarıdır.

Broadcast, root scope dan başlayarak bütün alt scope’ları yaydığı bilgiden haberdar edilebilir. Aşağıdaki resimde ifade edildiği şekli ile inceleyecek olursak, çalışma zamanında ilk MapController nesnesi Dom üzerine yerleştiğinde hiyerarşik olarak üst scope’dan aşağı doğru tüm scope’ları haberdar etmektedir.

Emit, yönteminde ise resimde görüldüğü üzere sadece parent scope’lar bilgilendirilir.

Angularjs Custom Directive Serisi-5 Direktif Kalıtımı

12 Eki
  1. Direktiflerin Tanımlanması
  2. Direktif Restriction Yapısı
  3. Scope Ayrımı
  4. Ayrılmış Scope Tarafına Erişim
  5. Direktif Kalıtımı (Inheritance)

Angularjs direktif serisinin beşinci bölümü direktiflerin kalıtımı(directive inheritance) hakkında olacak.

Direktif kalıtımı, mevcut bir direktifin özelliğini kullanarak yeni bir direktif oluşturmak istediğimizde kullanabileceğimiz bir özelliktir.

Direktiflerin kalıtımı controller birimlerinin paylaşımı şeklinde olmaktadır. Alt direktifler, üst direktiflerin controller nesnelerine erişebilir.

Bu durumu daha iyi özetlemek amacıyla bir örnek üzerinden devam edelim. Örnek uygulamamızda araçları temsil eden vehicle isimli bir ana direktif olsun. Otobüs ve taksiler birer araç olduğundan onları da alt direktifler olarak düşünebiliriz.

 
 <vehicle>
    <bus></bus>
    <car></car>
 </vehicle> 

Örnek uygulamamızda bus ve car direktifleri yolcu taşıyan araçları temsil etmektedir. Her araca yolcu bindiğinde vehicle isimli ana direktif üzerinde araçların toplam yolcu sayısının kaydı güncellenmektedir.

angular.module("app", [])
   .directive("vehicle", function(){
      return {
         restrict: "E",
         controller: function($scope){
           var self = this;

          self.totalPassenger = 0;
          self.loadPassenger = function(count){
               self.totalPassenger += count;
          }

          $scope.totalPassenger = function(){
              return self.totalPassenger;
          }
       }
     }
})

vehicle direktifinin self.loadPassenger() metodu, diğer alt direktifler tarafından yolcu sayısını güncellemek için kullanılacak olan metottur.

angular.module("app")
   .directive("bus", function(){
       return {
          restrict: "E",
          require: "^vehicle",
          scope: {},
          link: function(scope, element, ettributes, vehicleController)           {
              scope.dailyPassengersCount = 0;
 
              setInterval(function(){ 
                 scope.$apply(function(){
                    var loadedPassengers = Math.floor((Math.random() * 15) + 1)
                    scope.dailyPassengersCount += loadedPassengers;
                    vehicleController.loadPassenger(loadedPassengers);
                })
              }, 2000);
          },
          template: '<span>Bus Total Passengers: {{dailyPassengersCount}}</span>'
      }
 })

bus direktifine require:”^vehicle” eklemesi yapılarak bir üst direktifin vehicle olduğunu bildiriyoruz. Direktifin link() fonksiyonuna dikkat edecek olursak dördüncü parametresi vehicleController olarak belirlenmiştir. Bu controller, kalıtımı yapılan direktife ait controller nesnesidir.

bus direktifi 2 saniyede bir rastgele olarak yolcu sayısını arttırmaktadır. bus direktifi kendi günlük toplam yolcu sayısını arttırırken, bir üst direktif olan vehicle direktifinin de toplam yolcu sayısını güncellemektedir.

Aynı şekilde car direktifini de aşağıdaki gibi tanımlayabiliriz.

angular.module("app")
   .directive("car", function(){
      return {
        restrict: "E",
        require: "^vehicle",
        link: function(scope, element, ettributes, vehicleController) {
            scope.dailyPassengersCount = 0;
 
            setInterval(function(){ 
              scope.$apply(function(){
                 var loadedPassengers = Math.floor((Math.random() * 4) + 1);
                 scope.dailyPassengersCount += loadedPassengers;
                 vehicleController.loadPassenger(loadedPassengers);
              })
           }, 1500);
        },
        template: '<span>Car Total Passengers: {{dailyPassengersCount}}&</span>'
    }
 })

Çalışan uygulamayı şu şekilde görebiliriz.

Angularjs Custom Directive Serisi-4 Ayrılmış Scope Tarafına Erişim

9 Eki
  1. Direktiflerin Tanımlanması
  2. Direktif Restriction Yapısı
  3. Scope Ayrımı
  4. Ayrılmış Scope Tarafına Erişim
  5. Direktif Kalıtımı (Inheritance)

Angularjs direktif serisinin üçüncü bölümünde scope ayrımı üzerinde durmuştuk. Bu bölümde ise ayrılmış(isolated) scope bölgelerine dışarıdan erişimin nasıl yapılacağı üzerinde duracağız.

Bir direktifin scope ayrımını yaparken direktif nesnesine scope:{} şeklinde bir üye eklemesi yapılmaktadır. Bu durumda direktifin dış bağlantısı kesilir.  Ayrılmış direktiflerin dışındaki bir controller scope bölgesine veya başka bir direktifin scope bölgesine erişmek mümkün değildir. Ancak direktif tarafında belirlenen dış üyelere izinler verilerek onlara erişmek mümkündür. Bunu üç farklı şekilde yapabiliriz.

  • “@”
  • “=”
  • “&”

“@” scope erişimi

Direktif dışındaki bir değişkenin metinsel değerine erişmek için kullanılır.


Bu örnekte ColorController içerisinde tanımlanmış olan $scope.hex değişkeninin metin değerine ulaşılmıştır. Yani @ scope türü string değerlere erişimi sağlar.

Dikkat edecek olursak HTML tarafında kullanım <color hex=”{{hex}}”></color> şeklindedir.

“=” scope erişimi

Direktif dışındaki değişkenin kendisine erişmek için kullanılır.

Dikkat edecek olursak HTML tarafında kullanım <color hex=”hex”></color> şeklindedir. Yani metinsel değere erişim olmadığından “{{}}” şeklinde bir kullanım yapılmıyor.

“&” scope erişimi

Direktif dışındaki bir fonksiyona erişmek için kullanılır. Bir başka deyişle direktifin dışındaki bir controller scope üzerindeki fonksiyona direktif tarafından erişmek için kullanılır. Örneğin metin kutusuna tıklandığında rastgele renk kodu üreten bir direktif için aşağıdaki örneği inceleyebilirsiniz.

 

Angularjs Custom Directive Serisi-3 scope izolasyonu

8 Eki
  1. Direktiflerin Tanımlanması
  2. Direktif Restriction Yapısı
  3. Scope Ayrımı
  4. Ayrılmış Scope Tarafına Erişim
  5. Direktif Kalıtımı(Inheritance)

Angularjs direktif serisinin üçüncü bölümü direktiflerin scope ayrımı(isolate scope) hakkında olacaktır. scope ayrımı yapılırken iki önemli nokta vardır. Birincisi direktifin üst scope bölgelerinden ayrıştırılması. İkincisi direktiflerin ortak scope bölgelerinden ayrıştırılmasıdır.

1-Direktifin Üst scope Bölgelerinden Ayrıştırılması

Direktifler varsayılan olarak bir üst scope bölgesine erişebilecek şekilde ayarlanmıştır. Ancak her direktifin kendine ait bir scope bölgesi de vardır.

Bu direktif bir üst scope tarafından gelen location nesnesine ait bilgilere erişebilmektedir.

 <div ng-controller="LocationCtrl">
    <location></location>
</div>

Yani LocationCtrl içerisinde tanımlanan $scope.location nesnesine direktif tarafından doğrudan erişim sağlanabilmektedir. Bunu önlemek için direktif nesnesine scope:{} şeklinde bir tanımlama yapılır.

Artık LocationCtrl içerisinde tanımlanan $scope.location nesnesine direktif tarafından doğrudan erişilemez.

2-Direktifin Ortak scope Bölgelerinden Ayrıştırılması

Direktifler tanımlanırken data binding işlemi sırasında bir karışıklığa sebep olmamak adına scope ayrımını doğru yapılması gerekmektedir.

Örneğin renk kodlarını hexadecimal bir biçimde kullanıcıdan almayı amaçlayan  bir direktifimiz olsun.

Bu direktifi üç farklı renk için kullanmak istediğimizde aşağıdaki gibi bir durum ortaya çıkacaktır.

Adsız

Bir renk kutusuna bir değer girdiğimizde diğerleri de aynı değeri alıyor. Bunun sebebi hex değişkeninin two-way-binding yani çift yönlü bağlantısı yaptığı halde direktifin scope bölgesinin ayrılmamış olmasıdır. Direktifin scope bölgesini ayırmak için scope:{} şeklinde bir tanımlama yapılır.

Adsız

Bu şekilde her direktifi kendi scope bölgesinde çalışabilir hale getirmiş oluruz.

Dan Wahlin direktif scope ayrımı için durumu özetleyen bir grafik hazırlamış.

image_thumb_56FB9433 (1)

Bu grafiğe göre bir direktif bir üst controller’a ait scope bölgesine erişebiliyor ise shared yani paylaşılmış scope oluyor. Eğer erişemiyorsa isolated yani ayrılmış oluyor.

 

Angularjs Custom Directive Serisi-2 Direktif Restriction Yapısı

6 Eki
  1. Direktiflerin Tanımlanması
  2. Direktif Restriction Yapısı
  3. Scope Ayrımı
  4. Ayrılmış Scope Tarafına Erişim
  5. Direktif Kalıtımı (Inheritance)

Angularjs direktif serisinin ikinci bölümünde direktiflerin restrict üyesi üzerinde duruyor olacağız.

Adsız

Bir direktif için restriction tanımlaması onun görünüm tarafında ne şekilde kullanılacağının göstergesidir. Direktif nesnesinin dört farklı restrict şekli vardır.

  1. ‘A’ attribute türünde direktifler
  2. ‘E’ element türünde direktifler
  3. ‘C’ class türünde direktifler
  4. M‘ yorum türünde direktifler

1- Attribute (A) türünde direktif tanımlama

Bu tür direktifleri mevcut HTML elementler içerisinde direktif adını attribute şeklinde çağırarak kullanabiliriz. Örneğin uzun bir metnin 50 karakterlik kısmını gösterip geri kalanını “…” şeklinde kısaltarak gösteren örnek bir direktif hazırlayalım.

Direktifin adı truncate ve işlevi bir metnin 50 karakterini gösterip geri kalanını kırpmaktır. Kullanım şekli yukarıda HTML kısmında göründüğü gibi <p truncate /></p> şeklindedir.

2- Element (E) türünde direktif tanımlama

Element türündeki direktifleri mevcut bir HTML element içerisinde tanımlanmak zorunda değiliz. Bu direktiflerin kendisi HTML element gibi kullanılır. Örneğin bir lokasyon bilgisini longitude(boylam) ve latitude(enlem) şeklinde standartlaştırarak yazdıran bir direktif element türünde oluşturulabilir.

HTML kullanımı <location lon=”23.52″ lat=”42.12″></location> şeklindedir ve enlem boylam bilgileri değişken olarak belirtilmektedir. HTML attribute şeklinde belirtilen değişkenler direktifin scope üyesine aktarılmaktadır. Direktifin scope üyesine link fonksiyonundan erişilebilmektedir.

Direktiflerin link() fonksiyonunun parametreleri dependency injection yöntemiyle verilmez. Parametreler belli bir durum sırasına göre(positional) sıralanmıştır. Sıralama scope, attribute, element, controller şeklindedir.

3- Class (C) türünde direktif tanımlama

Direktifleri HTML elementlerinin class özelliklerini belirlemek için kullanabiliriz. Bu tür direktifler sadece class özelliği için çalışırlar. Örneğin 10 karakterden uzun metinleri kırmızı olarak işaretleyen bir direktif class türünde tanımlanabilir.

4- Comment (M) türünde direktif tanımlama

HTML tanımlaması içerisinde yorum satırı için tanımlanan direktif tipleridir. Yorum direktiflerinin tanımlanması diğer direktifler gibidir.

 app.directive("comment", function() {
    return {
        restrict: 'M',
        template: '<div>Yorum satırı...</div>'
    }
 })

Kullanım şekli de <! – – directive:comment – – > şeklindedir.

Direktifler için yukarıda tanımlanan 4 restrict özelliğinden en sık kullanılanlar element ve attribute şeklinde tanımlanan direktif türleridir.

Angularjs Custom Directive Serisi-1 Direktiflerin Tanımlanması

5 Eki

Direktifler Angularjs framework yapısı içerisindeki en önemli kavramlardan biridir. Direktifler HTML attribute ve elementler ile ulaşılabilen yeniden kullanılabilir ve test edilebilir kod blokları oluşturmayı sağlar.

Bu yazının konusu Angularjs direktifleri konusuna giriş niteliğinde olup, direktifler ile ilgili bir yazı dizisinin de başlangıcıdır. Bu yazı dizisinde kendi özel direktiflerimizi oluşturup kullanmayı ve direktiflerin detaylarına değineceğiz. Konu başlıkları genel olarak şu şekilde olacaktır:

  1. Direktiflerin Tanımlanması
  2. Direktif Restriction Yapısı
  3. Scope Ayrımı
  4. Ayrılmış Scope Tarafına Erişim
  5. Direktif Kalıtımı (Inheritance)

Özel direktiflerin tanımlanmasına geçmeden önce Angularjs bünyesinde bulunan başlıca direktifleri inceleyelim.

  • ng-show: Bir HTML elementinin gösterilmesini sağlar.
  • ng-hide: Bir HTML elementinin gizlenmesini sağlar.
  • ng-click: Bir HTML elementine tıklandığında çalışacak fonksiyonu gösterir.
  • ng-class: Bir HTML elementin class özelliğini belirler.
  • ng-style: Bir HTML elementin style özelliğini belirler.
  • ng-repeat: Bir HTML elementi tekrarlı bir sırayla yazar.

Örnek kullanım şekilleri:

 <button ng-show="isVisible"></button> 
 <button ng-hide="isSecret"></button> 
 <button ng-click="sendMessage()"></button> 
 <button ng-class="big-button"></button> 
 <utton ng-style="yellow"></button> 
 <button ng-repeat="item in socials"></button> 

Angularjs bünyesindeki bu direktiflerin ihtiyacımızı karşılamadığı durumlarda kendi özel direktiflerimizi oluşturabiliriz. Kendi özel direktiflerimizi oluştururken dikkat etmemiz gereken bazı kurallar vardır. Bu kurallar olmazsa olmaz katı kurallar olmaktan ziyade ilkesel olarak  benimsenmiş kurallardır. Örneğin direktiflerin isimlendirilmesi dikkat edilmesi gereken kurallardan biridir.

Direktifleri nasıl isimlendirmeliyiz?

Direktifler isimlendirilirken kullanıcıların okuduklarında kolayca anlayabilecekleri ve birbiri ile çakışmayan benzersiz ön ekler kullanmaya özen gösterilmelidir. Kendi özel direktiflerimizi kullanırken “ng-“ ön ekini kullanmamalıyız. Çünkü “ng-“ angular tarafından belirlenmiş özel bir ön ektir. Bunun yerine iki harf ile belirlediğimiz özel ön ekler kullanmayı tercih edebiliriz.

Direktiflerin javascript tarafındaki isimlendirme şekli Camel Casing şeklinde  yapılmaktadır. Örneğin javascript tarafında “mySocialButtons” gibi bir isimlendirme tercih edebiliriz.

angular.module("directives", [])
    .directive("mySocialButtons", [function(){..}]

Angularjs  HTML tarafından direktife erişirken, bu isimlendirmeyi küçük harfler ve her kelimenin arasına “-” karakteri kullanarak çağırmaya izin verir. Örneğin HTML tarafında “my-social-buttons” şeklinde direktifimizi çağırabiliriz.

 <my-social-buttons> </my-social-buttons>

Özel direktifleri ne zaman tercih etmeliyiz?

  • Tekrar tekrar kullanılabilir HTMl bileşenleri oluşturmak istediğimiz durumlarda kullanabiliriz.
  • Elementlere aynı davranışları vermek istediğimizde kullanabiliriz.
  • Bir jQuery plugin ile çalışmak istediğimiz durumda onu paketlemek için kullanabiliriz.
  • DOM ile etkileşime geçmek istediğimiz her zaman direktifleri kullanabiliriz. Controller, Service ve Factory gibi bölümlerden DOM elementlerine erişmek kötü bir yöntemdir. Çünkü kodun test edilebilirliğini azaltır ve kodu DOM’a bağımlı hale getirir.

Direktiflerin Tanımlanması

Direktiflerimizi oluşturmadan önce direktiflerin tutulacağı modülleri oluşturmalıyız. Bu ayrımın sebebi direktiflerin ana uygulama modülünden bağımsız ve test edilebilir özellikte olmasıdır. Ana modül içerisinde her şeyin tanımlanması karmaşık bir uygulamanın oluşmasına neden olacaktır. bu nedenle ana uygulamamızın bulunduğu modülü özel direktiflerimizi tanımlamak için kullanmamalıyız. Direktif modülünü uygulama modülüne sonradan yüklemeliyiz.

 

Örnek uygulamanın konusu, her web sitesinde karşılaştığımız sosyal medya butonlarını tekrar tekrar kullanabilmek için bir direktif haline getirmektir. Görüldüğü üzere ana modül app şeklinde isimlendirilmiştir. Direktifin tanımlanacağı modül directives adlandırılmış ve ana modüle sonradan yüklenmiştir. Eğer ana modül ile ilgili bir direktif oluşturacaksanız app modülüne bağlı bir şekilde tanımlamanızda bir mahsur yoktur.

Direktif fonksiyonu bir nesne döndürmektedir. Bu nesnenin bazı üyeleri vardır. Bu üyeler şu şekildedir:

  • restrict
  • scope
  • template veya templateUrl
  • link
  • controller

Direktifin restrict üyesi

Bu nesnenin restrict özelliği direktifin tipini belirler. Direktiflerin dört farklı tipi vardır. Bunlar:

  • ‘A’ attribute türünde direktifler
  • ‘E’ element türünde direktifler
  • ‘C’ class türünde direktifler
  • M‘ yorum türünde direktifler

Direktifin scope üyesi

Direktifin faaliyet alanını(scope) belirler.Direktifler veri bağlantısını kendi faaliyet alanlarından(scope) alabilecekleri gibi direktif dışındaki bir direktiften veya controller’dan da sağlayabilir.

Direktifin template üyesi

Direktifler DOM üzerine yerleştiklerinde görüntülenmek isteniyorsa HTML tanımlamaları yapılmalıdır. HTML tanımlaması düz metin şeklinde yapılabileceği gibi dışarıdaki bir *.html dosyaya templateUrl ile erişilerek de yapılabilir. Yukarıdaki örnekte templateUrl kullanılmıştır.

Direktifin link üyesi

Direktifin link() fonksiyonu direktifin DOM elementi ile temasa geçtiğinde yani uygulama yüklendiğinde çalışır. DOM içerisinde her direktif örneği (instance) için bir kez çalışır. Bunu test etmek için link() fonksiyonu içerisine console.log(“work”) yazabilirsiniz. Konsola sadece bir kez “work” yazdığını gözlemlyebilirsiniz.

Direktiflerin link() fonksiyonunun parametreleri dependency injection yöntemiyle verilmez. Parametreler belli bir durum sırasına göre(positional) sıralanmıştır. Sıralama scope, attribute, element, controller şeklindedir.

Direktifin controller üyesi

Bir direktif eğer dışarıdan veri almaya ihtiyaç duymuyorsa yani sadece görünüm(view) taraflı bir yaklaşımı varsa bu tür direktifler görünüme dayalı (view oriented) olarak düşünülebilir. Bunlar basit direktiflerdir. Ancak kendi verisini kendi temin edebilen direktifler oluşturmak isteniyorsa ki bu tür direktifler veriye dayalı (data-oriented) direktiflerdir. Bu tür direktiflere controller üyeleri eklenir. Bir controller ile direktifin servisler aracılığı ile dışarıdan kendi verisini alması sağlanabilir. Eğer mantıksal iş kuralları varsa yine controller içerisinde tanımlanabilir.

Eğer bir direktif görünüm tarafı ve kontrol tarafı ile bütünleşik olarak tanımlanmış ise bu tür direktifler component ya da widget diye adlandırılabilir. Direktifleri yazının en başında bahsettiğim kadar önemli kılan şey, ihtiyaç duyduğu bir çok özelliği bünyesinde taşıyabiliyor olmasıdır.

Angularjs 2.0 ve sonrası için direktifler daha da önemli hale gelecek. Çünkü artık tek başına controller yapılarının olmadığı yeni bir sürüm yolda gibi görünüyor.

Angularjs direktif template belirleme ve $templateCache servisi

12 Eyl

Angularjs direktiflerinin görünüm tarafını template özelliği üzerinden belirleyebiliriz. Template özelliğini belirlemenin bazı yöntemleri vardır. Bunlar:

  • Düz metin şeklinde belirleme
  • URL ile dosya yolunu göstererek belirleme
  • $templateCache servisi ile belirleme

Bu işlemleri örnek bir personel kartı tanımlayarak gerçekleştirmeye çalışalım.

Düz Metin Şeklinde Template Belirlemek

Direktiflerin template özelliğini düz metin şeklinde belirlemek aşağıdaki yöntem izlenmelidir.

 

URL ile Dosya Yolunu Göstererek Belirleme

Bu yöntemde templateUrl özelliği olarak bir html dosya yolu verilir. HTML dosya üzerinde istediğimiz gibi düzenlemeleri yaparak yolunu bu şekilde direktife kolayca verebiliriz.

 

$templateCache Servisi ile Belirleme

URL ile template belirlerken yapılan işlem önceden hazırlanmış bir HTML dosyasının yolunu templateUrl özelliğine bildirmektir.

$templateCache servisini kullanırken HTML metinini önceden servise belirtmek gerekmektedir. Servisin kullanımı put() ve get() metodları üzerinden yapılmaktadır.

  • $templateCache.put(“templateAdı”, “template içeiği”)
  • $templateCache.get(“templateAdı”)

Template içeriğini uygulama başlatılırken yani modülün run fonksiyonu çalıştırıldığında gerçekleştirebiliriz.

 

$templateCache içerisindeki veriye templateUrl üzerinden aşağıdaki şekilde erişmek mümkündür.

Not: Angularjs uygulamalarında script şeklinde tanımlanan html içerikleri doğrudan $templateCache içerisine kaydedilir.

Bunu şu şekilde inceleyebiliriz:

Burada html içeriği script olarak tanımlanmıştır ve id değeri olarak card.html verilmiştir. İçeriğe javascript tarafından $templateCache.get(‘card.html’) şeklinde erişilebilmektedir.

Angularjs Proje Yönetimi

8 Eyl

Yazılım projelerinin geliştirilmesi sırasında karşılaşılan bazı genel problemler vardır. Bu problemler yazılımın Frontend veya Backend olmasına bağlı olmayan, sürecin gelişimi sırasında ortaya çıkan problemlerdir.

Projelerde istenen taleplere bağlı olarak yazılımda çok fazla kod olabilir. Kod sayısı arttıkça yazılımın çalışma performansı da düşmeye başlar. Bir süre sonra kodu yönetemez hale gelirsiniz. Artık kod sizi yönetmeye başlar ki bu durumda yeterki  çalışsın mantığıyla bir dizi mantıksız işler yapmaya başlayabilirsiniz. Bu gibi durumlarla başa çıkabilmek için uyguladığınız yöntemlerde kod sayısı artsa bile kodda karmaşıklığın oluşmaması gerekmektedir. Yani bir sene süren bir projede ilk gün nasıl kafa karışıklığı olmadan rahatça kod eklenebiliyorsa, son günde de aynı rahatlıkla kod eklemesi yapılabilmelidir. Modüler yapılar kullanarak bir şekilde kodun karmaşasını azaltabiliriz, bu sefer de modül sayıları artar ve iş süreleri uzamaya başlar.

Bu noktada işlerimizi önemli ölçüde kolaylaştıracak olan araçlar Framework’lerdir. Bizim yapmamız gereken bir takım işleri Framework’lere yüklemek zaman kazanmak açısından önemlidir. Her framework amaca uygun olmayabilir. Bu nedenle Framework seçiminde kolay kullanılabilirlik, sürekli güncellenme, performans ve geniş topluluklar tarafından kullanılıyor olmak önemlidir.

Angularjs bu açıdan bakıldığında yapılabilecek en doğru seçimlerden birisidir. Üretim ve destekleme tarafında Google vardır ve çok yaygın kullanılan bir Framework’dür. Kullanım açısından son derece kolaydır. Model ve View tarafındaki ayrımı yapabilmesi (MVC mimarisi) ve modüler geliştirmeye imkan sağlayan yapısı sayesinde kullanıcı dostu bir yapısı vardır.

Angularjs Yapı Taşları

Angularjs kendine özgü bir mimari üzerine geliştirilmiştir. Belli yapı taşları üzerine oturtulmuş bir düzen söz konusudur. Bunlar:

  • Module
  • Config
  • Route
  • Controller
  • View
  • Directive
  • Filter
  • Service
  • Factory

şeklinde sıralanabilir.

Angularjs Proje Yapılandırması

Angularjs ile yapılandırılacak projeler mimari açıdan önemlidir. Biz geliştiricilere düzgün kod yazabilmek için birçok imkanı sunan bir framewrok ile spagetti kod oluşturmamak lazım. Bu açıdan angularjs ile çalışırken dikkat edilmesi gereken bazı hususları aşağıda başlıklar halinde ele alınmıştır.

Modüler Yapı

Müşterinin her talebi için uygulamayı bölümlendirmek ve her bölüm için farklı bir modül oluşturulmalıdır. Geniş ölçekli bir uygulama geliştirirken her bileşeni tek bir modül altına toplamak yerine iş mantığına göre tasarlanmış birden fazla modül ile çalışmak daha uygun olacaktır. Örnek olarak Email Hizmeti veren bir uygulama için modüller şu şekilde olabilir:

angular.module("Epostalar", []);
angular.module("GelenKutusu", ["Epostalar"]);
angular.module("EpostaServisi", ["GelenKutusu"]);

Model Servisleri

Angularjs tarafından sunulan Dependency Injection yapısı sayesinde soyutlamalar kolayca yapılabilmektedir. Servis yapısı ile modüller arasında izolasyonlar yapılmalıdır. Bu sayede servisler veya modüller arasında kod aktarımı ile iletişim sağlanabilir.

Oluşturulan servisler tek bir görevi yerine getirmelidir. Örneğin HTTP protokolü üzerinden bir dış kaynak ile veri alış verişi yapacak olan bir servis sadece o kaynakla konuşmalıdır. Veriyi almışken servise hadi ekranda listeleme de yapın şeklinde ikinci bir görev verilmemelidir. Aksi taktirde hep karşısında durduğumuz karmaşıklık problemine doğru ilk adımı atmış oluruz.

Kod Yapısı

Mümkün olduğunca az kod satırlarıyla hazırlanmış, gerektiğinde servisler aracılığı ile haberleşebilen modüller oluşturulmalıdır. Servis, Controller ve Template gibi kod birimlerinin içerikleri sade anlaşılır ve kısa tutulmalıdır.

HTML tarafındaki bir DOM elemanları üzerinde Controller veya Service gibi yapılar içinden erişip doğrudan işlem yapmamalısınız.

Controller sınıflarından dış kaynaklara erişilmemelidir. Bu işlemi servisler aracılığı ile gerçekleştirip, ilgili servislere controller tarafından erişim sağlanmalıdır. Veri kümelerinin controller içerisinde depolanması da yanlış bir davranıştır.

Görünüm Yapısı

Görünüm tarafındaki HTML elementlerini depoladığımız yapılara template denir. Template içerisinde sadece HTML kodları ve Angularjs direktifleri olmalıdır. İş kuralları bu kısımda tanımlanmamalıdır. Kurallar template tarafından erişilen controller içerisinde tanımlanmalıdır. Aksi taktirde görünümle alakası olmayan kural belirleme sorumluluğu controller tarafından alınıp görünüm tarafına yüklenmiş olur.

Görünüm tarafında sürekli güncellenmesi gerekmeyen içerikler için TwoWayBinding yerine OneWayBinding tercih edilmelidir.

Proje Dizin Yapısı

Proje yapısı şekillendirilirken dikkat edilmesi gereken bir diğer yapı ise proje dizin yapısının oluşturulmasıdır. Kod birimlerinizi HTML, CSS, JS gibi özelliklerine ve Angularjs yapılarına göre ayırmak ve dizinlere aktarmak sık kullanılan bir yöntemdir.

Dizin
Yanlış Dizin Yapısı

Bütün controller dosyalarını Controllers dizini altında dizini altında toplamak, zamanla dizin içerisinde onlarca belki yüzlerce dosya birikmesine neden olacaktır. Bu durumda aradığımızı bulmak daha fazla zaman alacaktır. Örneğin bir EmailApplication projesi için GelenKutusu modülünün controller kodu Controllers dizininde aranacak ve görünüm için hazırlanan template kod dosyası ise Templates dizininde aranacaktır. Bu şekildeki proje tasnifi “türe göre tasnif” olarak adlandırılır. Türe göre tasnif edilen projeler zamanla projelerin karmaşık bir hal almasına neden olur.

Bunun yerine iş mantığına göre planlanmış bir dizin yapısı oluşturmak daha uygun bir yöntem olacaktır.

Uygun Dizin Yapısı
Uygun Dizin Yapısı

Email hizmeti ile ilgili iş kurallarını ve dosyalarını tabakalandırarak çalışmak daha uygun bir seçim olacaktır. Bu şeklide proje tasnifine ise “özelliğe göre tasnif” denir. Bu durumda Email listemizdeki kişilerle ilgili işlemlerin Contacts dizininde olduğunu özellik bakımından kolayca anlayabiliriz. Hem görünüm hem kullanım açısından sade ve anlaşılır bir yöntemdir.

Kodun organizasyon yapılandırması tamamen ekibinize veya size kalmış bir seçimdir. Bir dayatma söz konusu değildir. Temel nokta, kodun iyi bir şekilde ayrıştırılması ve ayrıştırılan bölümlerin yeni bir karmaşaya yol açmamasıdır.

Bu yazıda angularjs projeleri oluşturulurken dikkat edilmesi gereken önemli hususlardan bahsetmeye çalıştık. Umarım faydalı olmuştur. Bir sonraki yazıda görüşmek dileğiyle.

Angularjs ngResource ile RESTful veri iletişimi

4 Eyl

Bu yazıda angularjs ile proje geliştirirken REST servislere erişerek veri talep etmek için kullanılmak üzere hazırlanmış bir modül olan ngResource modülünü incelemeye çalışacağız.

ngResource modülü angular.js script dosyası içerisinde bulunmaz. Projemize ngResource modülünü dahil edebilmek için angular-resource.js javascript dosyasını projemize dahil etmeliyiz.

<script src="angular.js">
<script src="angular-resource.js">

Modülü bağımlı modül olarak projemize ekleyerek uygulamamıza yükleyebiliriz. Yükeleme işlemini şu şekilde yapabiliriz.

angular.module('app', ['ngResource']);

Yükleme işlemi gerçekleştikten sonra RESTful servislere erişmek için modül içerisinde bulunan $resource servisini kullanabiliriz. $resource servisi kendi içerisinde $http servisine bağımlıdır ve bu servis sayesinde sunucu ile iletişime geçebilir. $resource servisinin kullanım şekli kısaca aşağıdaki gibidir.

$resource(url, [paramDefaults], [actions], options);

Servisin REST uçları ile konuşabilmek için bazı metodları vardır. Bunlar:

{ 'get':    {method:'GET'},
  'save':   {method:'POST'},
  'query':  {method:'GET', isArray:true},
  'remove': {method:'DELETE'},
  'delete': {method:'DELETE'} };

Örnek olarak bir REST ucumuz aşağıdaki şekilde olsun. Bu uçla $resource servisi aracılığı ile işlemler yapmaya çalışalım.

  • http://location.bayramucuncu.com/api/location => GET  ile lokasyonlar listelenir.
  • http://location.bayramucuncu.com/api/location => POST ile yeni lokasyon ekler.
  • http://location.bayramucuncu.com/api/location/:id => GET tek lokasyon getirir.
  • http://location.bayramucuncu.com/api/location/:id => PUT lokasyon günceller.
  • http://location.bayramucuncu.com/api/location/:id => DELETE lokasyon siler.
angular.module('location.services')
 .factory('Endpoint', function($resource) {
    return $resource('http://location.bayramucuncu.com/api/entries/:id',
              {
                   id: "@id"
              },
              {
                   update: { method: "PUT" }
              }
    );
 });

Burada {update: { method: “PUT” }} şeklinde özel bir fonksiyon tanımlanmıştır. Çünkü  HTTP PUT metodu, $resource içerisinde standart bir kavram olarak ele alınmamıştır.

Diğer bir  parametre olan {id: “@id”} ise URL adresinin sonundaki “/:id” ifadesini değişken hale getirmek için tanımlanmıştır.

Artık controller içerisinde $resource servisinin metodlarını kullanabiliriz.

angular.module('location.controllers')
       .controller('LocationIndexCtrl', function($scope, Endpoint) {
           Endpoint.query(function(response){
              $scope.locations = response;
           });
       })
       .controller('LocationDetailCtrl', function($scope, Endpoint) {
           var parameter = { id: 1 };
           Endpoint.get(parameter, function(response){
              $scope.location = response;
           });
       })
       .controller('LocationCreateCtrl', function($scope, Endpoint) {
           var location = {
                name: "blue restaurant",
                lon: "123"
                lat: "456"
           };
           Endpoint.save(location, function(response){
              alert("new location created");
           });
       })
       .controller('LocationUpdateCtrl', function($scope, Endpoint) {
           var location = {
                name: "blue restaurant",
                lon: "123"
                lat: "456"
           };
           Endpoint.update({ id:1 }, location, function(response){
              alert("location updated");
           });
       })
       .controller('LocationDeleteCtrl', function($scope, Endpoint) {
           var parameter = { id: 1 };
           Endpoint.delete(parameter, function(response){
              alert("location deleted");
           });
})

Bu şekilde REST servisi işlemleri için her metoda karşılık bir controller oluşturmuş olduk. İsterseniz tek bir controller içerisine her HTTP metodu için bir fonksiyon da tanımlayabilirsiniz.

Angularjs ile asenkron işlemler gerçekleştirilirken kullanılan $promise nesnesine $resource servisi üzerinden erişmek de mümkündür.

angular.module('location.controllers')
       .controller('LocationIndexCtrl', function($scope, Endpoint) {
           Endpoint.query().$promise.then(
              function(response){
                 $scope.locations = response;
              },
              function(error){
                console.log("Hata oluştu!");
              }
           );
       })
})

Bu yazıda ngResource modülünün REST uçları ile nasıl konuşabileceğimizi incelemiş olduk. Bir sonraki yazıda görüşmek dileğiyle.