Ağu.20

AngularJS (1.3 / 1.5) Eğitimi: Direktifler (Directive)

Direktifler, AngularJS’nin en başta gelen temel bağlantı elemanlarından biridir. HTML5 sayfa yapısında yer alan elementlere direktifler ile erişilir ve yönetilir.

Direktifler birer attribute olarak tanımlanır. Bazıları değer alabilirken bazıları sadece anahtar kelime olarak bile tanımlama yapmak için yeterlidir.

Direktifler ng- ön eki ile başlar ve diğer isimlerle direktifler türetilir.

Temel olarak AngularJS’deki direktifler aşağıdaki tabloda verilmiştir.

Listede yer alan direktifler, AngularJS’de en başta bilmeniz gerekenlerdir. Listedekiler dışında onlarca direktif bulunmaktadır. AngularJS direktiflerinin tam listesine erişmek için https://docs.angularjs.org/api/ng/directive adresine bakabilir ve inceleyebilirsiniz. Ayrıca kitabın ilerleyen konularında bir web sitesi yapma uygulamasında, bölüm içinde yer almayan bazı direktiflerin de uygulamalarını göreceksiniz. Şimdi listede yer alan direktiflerin kullanım yöntemlerini inceleyelim.

ng-app

Daha önce de görmüştük, tekrar edelim. Genelde html ng-app veya body ng-app etiketlerinde kullanılır. Ancak dilerseniz spesifik bir alanda da AngularJS’nin kapsama alanını belirtebilirsiniz.

ng-init

Bunu da daha önce görmüştük, hatırlayın. AngularJS kapsama alanı tanımlandığında değişkenleri (sayı, metin, obje ve dizi) tanımlamak için kullanılır. ng-app ile birlikte eş zamanlı kullanıldığına dikkat edin!

<div ng-app ng-init = "sayilar = [sayi=3, sayi=5]; metinler = {isim:'Uğur', soyisim:'Gelişken'}" >

ng-model

Bunu da daha önce gördük yine. Bir değeri alıp DOM içinde {{ }} ifadesi içinde kullanmamızı sağlar. Değeri alabilmek için de DOM elementini bir model olarak tanımlayıp model isimi belirtmemiz gerekir. Model ismi “ “ çift tırnak ile belirtilir, değişken tanımlama kurallarına uyulur.

<body ng-app>
    <input type="text" ng-model="isim" />
    <div>
       Merhaba {{isim}}
    </div>
</body>

Burada oluşturduğumuz her bir model, AngularJS’de scope olarak tanımladığımız değişken kapsama alanı altında tutulacaktır. Yani scope ile Controller içinden bu değerlere ulaşabiliriz. İlerleyen konularda göreceksiniz, şimdiden bu bilgiyi aklınızın bir köşesine not edin.

ng-controller

Bu direktifi daha önce Şablon, Modüller ve Kontroller başlığı altında incelemiştik, o konuyu inceleyebilirsiniz.

ng-bind

scope veya ng-model ile bir veriyi alıp DOM elemanına bağlamada kullanılır.

<body ng-app="">
    <div>
      <div>İsminiz: <input type="text" ng-model="isim" /></div>
      <div> Merhaba <span ng-bind="isim"></span></div>
    </div>
</body>

ng-repeat

Bir işlemi tekrarlamada kullanılır. Şimdi bir tablo çizdirme örneği yapalım. Yapacağımız örneğimizde ng-int içinde bir dizi tanımlayıp, bu dizi elemanlarını alt alta bir tabloda gösterelim.

<body ng-app ng-init = " hayvanlar=['Kedi', 'Köpek', 'At'] ">
    <div ng-repeat="hayvan in hayvanlar" style="border:1px solid black;padding:5px">
        {{hayvan}}
    </div>
</body>

ng-readonly

DOM elementinin (veri girişi ile ilgili olanlar) içeriğinin sadece okunabilir veya yeniden düzenlenebilir olmasını sağlar. True değeri alırsa sadece okunur olur.

<div ng-app>
    <input ng-readonly="false" type="number" placeholder="10" />
    <input ng-readonly="true" type="text" placeholder="AngularJS" />
</div>

Soldaki nümerik veri giriş kutusu aktifken, sağdakinin değeri değiştirilemiyor.

ng-disabled

True veya False değerlerini alarak DOM elemanının aktif veya pasif olmasını sağlar. Örneğimizde bir checbox’ın tıklanma durumuna göre bir metin kutusunu aktif veya pasif yapalım.

<body ng-app ng-init="secildimi=true" >
    <div>
      <input type="checkbox" ng-model="secildimi" />    
      <input ng-disabled="secildimi" type="text" value="..." />
    </div>
</body>

ng-init içinde bir değişken tanımlayıp Boolean değerini true olarak verdik. secildimi değişkenimizi checkbox elementimizin ng-model’i olarak tanımladık. Böylece bu seçim kutusu aktif veya pasif yapıldığında secildimi değişkeni true veya false olacaktır.

secildimi değişken değerini de text türünde bir metin kutusunda ng-disabled direktifinde parametre olarak kullandık. True değeri gelirse kutu pasif, False gelirse de kutu aktif olacaktır.


ng-click

Bir DOM elementinin tıklanması olayı ile tetiklenecek olan Controller fonksiyonu tanımlanır.

Yapacağımız örneğimizde Controller’ı HTML5 içinde sciprt etiketleri içinde tanımlayacağız. Burada farklı olarak $scope kavramını ve Controller içinde fonksiyon oluşturup bu fonksiyonu çağırmayı görelim. Aslında MVC yapısında bu şekilde Controller yapısı UI, yani VIEW içine dahil edilmez, fakat şimdi öğrenmeniz için ekledik. Detaylarını da zaten ilk konularda Template, Module, Controller konusunda öğrenmiştiniz.

Örneğimizde bir alışveriş listesi yapacağız. Ekle butonuna bastıkça bir dizide alacaklarımızı toplayıp sonra da liste ile yazdıracağız.

<!DOCTYPE html>
<html ng-app>
<head>
    <script 
        src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.29/angular.min.js">
    </script>
</head>
<body>
<div ng-controller="listeController" ng-init="alinacaklar=[];">
    Alınacaklar: <input type="text" ng-model="yeni" />
    <button ng-click="ekle()">Ekle</button>
    <p>Liste</p>
    <li ng-repeat="malzeme in alinacaklar"> {{ malzeme }} </li>
</div>
<script>
    function listeController($scope) {
        $scope.ekle = function() {
        $scope.alinacaklar.push($scope.yeni);
        $scope.yeni = "";
        }
    }
</script>
</body>
</html>

Kodlarımızı inceleyelim…

Etki alanını doğrudan html ng-app ile tanımladık.

div kutumuzu açarken ng-controller direktifi ile bu DOM içinde bir AngularJS Controller’ı tanımladık. Controller’ın adı listeController’dir. Bunu da etiketleri arasında oluşturduğumuz function listeController($scope){ } yapısı ile görmekteyiz. Demek ki Controller aslında bildiğimiz bir JavaScript fonksiyonundan başka bir şey değilmiş, boşuna korkmuşuz. Ancak dikkat edin, Controller yapısı ile oluşturulan bütün fonksiyonlar parametre değeri olarak $scope isminde bir değişken alır. Bu nesne, ng-app kapsama alanındaki bütün ng-model ile tanımlanan değerleri taşır. Yani bu nesne içinden ng-model ismi ile nesnelere ulaşılır.

ng-init direktifi içinde de malzemeler adında bir dizi tanımladık. Listemizdeki elemanlar burada toplanacak.

Controller içinde $scope.ekle = function() { } yapısı ile de bir metot tanımladık. JavaScript’te nesne yönelimli programlama yaklaşımımızı hatırlayın, aynı ona benziyor. Bu metodu da doğrudan Ekle butonunun ng-click direktifi ile çağırdık. Direktife değeri verirken sadece metodun adını ekle() şeklinde vermemiz yeterli. Yani $scope.ekle() derseniz hatalı olur.

ekle() fonksiyonunda da dizilere eleman ekleme metodumuz olan .push() ile $scope değer kapsama alanın içinde ng-model adı yeni olan input elemanının değerini ekledik. Sonraki satırda da metin kutusunun içini boşaltma işlemini “” işaretleri ile yaptık. Hepsi bu kadar!

Sayfa yüklendiğinde:

Birkaç malzeme eklendiğinde:

ng-show

Bir DOM elementini gizleyip tekrar gösterebiliriz. Şimdi biraz değişik bir örnek yapalım… Bir açılır listemiz olsun ve bu listeden seçilen elemanın değerine göre ilgili div kutusunu gösterelim.

Az önceki örneğimizde size v 1.2 ve v 1.4 üzeri yaşanan sorundan bahsetmiştim. Artık v 1.4’den sonra v 1.2’deki gibi aynı kalıp ile Controller kullanamıyoruz. Bunun yerine sayfada ng-app için bir isim belirleyip, bu isimle de bir Module oluşturmamız gerekiyor (Eski sürümleri de gösteriyorum ki; yarın öbür gün karşınıza gelirse şaşırmayın). Yine bu da çok basit bir işlem, meraklanmayın. Module kavramını öğrenmek için Modüller konusunu inceleyin.

Yapacağımız örneğimizde bir açılır menü içinde iki adet eleman yazdıracağız. Bunlardan biri Kedi, diğeri de Köpek. Bunların value özellikleri de kedi ve kopek’tir. Bu değerlere göre bir Module içindeki Controller içindeki metoda erişip, bu değerleri true veya false olarak değerlendirip ng-show için parametre olarak kullanacağız. Bu parametreler de sayesinde de id değerlerine gire

’leri gösterip gizleyeceğiz. div’lerin içinde de etiketleri ile ilgili hayvanın resmi bulunmaktadır.

Örneğimizde sadece ng-show direktifini kullanacağız. İsterseniz ng-hide ile de tersi durumu kontrol ettirebilirsiniz. Ayrıca ng-show yerine ng-if ile de true veya false değerlendirmesi yapabilirsiniz.

<!DOCTYPE html>
<html ng-app="hayvanlarAlemi" >
<head>
<meta charset=”UTF-8” />
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script>
  var uygulama = angular.module('hayvanlarAlemi', []);
  uygulama.controller("gosterKontrol", function($scope) {
        $scope.kontrolEt = function() {
          if ($scope.hayvanlar_liste == "kedi") {
            $scope.kediGoster = true;
            $scope.kopekGoster = false;
          } else {
            $scope.kediGoster = false;
            $scope.kopekGoster = true;
          }
        }
    });
</script>
<body>
    <div ng-controller="gosterKontrol">
	<select ng-model="hayvanlar_liste" ng-change="kontrolEt()">    
	    <option value="kopek" >Köpek</option>
	    <option value="kedi" >Kedi</option>
	</select>
    <div ng-show="kediGoster" >
	<img src="http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-297480.jpg" height="200px" width="250px" />
    </div>
    <div ng-show="kopekGoster" >
	<img src="http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-190223.jpg" height="200px" width="250px" />
    </div>
</div>
</body>
</html>


ng-if

Bir koşul sağlanması durumunu kontrol etmek için kullanılır. Yine bir Module içinde yer alan Controller içindeki Metot çağırılır ve bu metot ile True veya False değerleri elde edilir. Böylece işlemler yapılır.

Ayrıca diğer bir kullanım metodu ile de doğrudan ng-if direktifi içinde de karşılaştırma yapabiliriz. İlk olarak doğrudan direktif içinde karşılaştırma işlemlerine, sonra da Controller kullanarak örnekler yapalım.

<body ng-app >
 <input type="text" ng-model="isim" />
 <div ng-if="isim=='uğur' ">
     Vay, sen misin?
 </div>
</body>

Bu örnekte, metin kutusuna uğur değeri girildiğinde yazı görünecektir. Karşılaştırma işleminde == eşitlik operatörü kullanıldı. Karşılaştırılan değer de metin olduğu için tek tırnak içinde yazdırıldı.

Bir de DEĞİL işlemini yapalım. Yani != operatörü…

<body ng-app >
 <input type="text" ng-model="isim" />
 <div ng-if="isim=='uğur'" >
     Vay, sen misin?
 </div>
  <div ng-if="isim!='uğur'" >
     Merhaba {{isim}}
 </div>
</body>

Doğrudan ng-if içinde bir işlem yaptırıp sonucunu değerlendirerek işlem yapalım.

<body ng-app >
 <input type="number" ng-model="sayi1" min="0" max="100" style="width:20" />
  <input type="number" ng-model="sayi2" min="0" max="100" style="width:20"/>
 <div ng-if="(sayi1*0.4 + sayi2*0.6) >= 50">
    Vize notu {{sayi1}} ve Final notu {{sayi2}} olduğu için %50 barajını açıp dersi geçtiniz.
 </div>
</body>

Şimdi de ikili karşılaştırma yapalım. Karşılaştırmada VE – VEYA mantıksal operatörlerini de kullanalım. Bunun için 2 adet checkbox kullanalım.

<body ng-app >
 <input type="checkbox" ng-model="onay1" />
 <input type="checkbox" ng-model="onay2" />
 <div ng-if="onay1 && onay2" >
    İki kutuyu birden seçtiniz.
 </div>
  <div ng-if="onay1 || onay2" >
    İki kutudan en az biri seçili.
 </div>
</body>

İkisi de seçilmediğinde:

İkisi de seçildiğinde:

Sadece biri seçildiğinde:

ng-class

Bir DOM elementinin class değerini okumaya veya değiştirmeye yarar. Yani bir CSS stilini bir elemente aktarabilmemiz daha kolay olabilir.

<body ng-app >
 <input type="button" value="Stil 1" ng-click="yeniClass='class1'" >
  <input type="button" value="Stil 2" ng-click="yeniClass='class2'" >
  <div>
     <p ng-class="yeniClass" >AngularJS</p>
  <div>
</body>

Öncelikle kodları inceleyelim…

ng-click direktifini daha önce görmüştük, nesneye tıklandığında işlem yapıyoruz. Bu işlemde yeniClass adında bir değişken oluşturup değerini class1 ve class2 olacak şekilde tanımlıyoruz. Tanımlanan bu isimler CSS3’te birer stil tanımlamasıdır.

p etiketinde ng-class direktifine de yeniClass ile oluşturduğumuz değişkeni atadık. Butonlardan birine tıklandığında class1 veya class2 ataması yapılacak.

CSS3 dosyamız da şu şekildedir:

.class1 {
  border: 4px solid blue; 
  color: red;
  padding: 10px;
  background-color: yellow;
}
.class2{ 
  color: blue;
  padding: 4px;
  background-color: pink;
}

Butonlara tıklandığında sırasıyla aşağıdaki gibi görünümler elde edilecektir.

ng-style

ng-class gibi stil ataması yapmak için kullanılır. Bu sefer CSS dosyası kullanmadan doğrudan Object nesnesi ile stilleri atayalım.

<body ng-app >
 <input type="button" value="Stil 1" ng-click="stil={'background-color':'red','color':'white'}" >
  <input type="button" value="Stil 2" ng-click="stil={'background-color':'white','color':'red'}" >
  <div>
     <p ng-style="stil">AngularJS</p>
  <div>
</body>

Butonlara sırasıyla tıklandığında aşağıdaki gibi görünecektir:

Özelleştirilmiş Direktif Oluşturmak, Etki Türlerini/Rollerini Belirlemek, Direktif ve Controller Arası Veri Değişimi

AngularJS’de tanımlanmış olan bazı direktifleri kullanmayı öğrendik. Ancak AngularJS sizin kendi direktiflerinizi oluşturmanıza da izin verir. Tabu bunun için Module kullanmanız gerekecektir.

İlk olarak DOM Element’leri için bir direktif hazırlayalım. Yani XML’de olduğu gibi kendi tanımlayacağımız bir element için direktif oluşturabiliriz. Direktif olarak tanımlayacağımız elementin geçtiği yerde de otomatik olarak direktif çalışacaktır.

<!DOCTYPE html>
<html ng-app="hakkimda" >
<head>
<meta charset=”UTF-8” />
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script>
  var hakkimda = angular.module('hakkimda', []);
  hakkimda.directive('ugurgelisken', function() {
    var directive = {};
    directive.restrict = 'E';    /* ELEMENT */
    directive.template = "Merhaba. Ben Uğur GELİŞKEN";
    return directive;
});
</script>
</head>
<body>
    <ugurgelisken></ugurgelisken>
</body>
</html>

Örneği incelediğimizde ng-app ile bir uygulama oluşturduk. Uygulama ismi hakkimda. Bu sayfada ugurgeliske şeklinde bir etiket açtım, ama içi boş. İçini AngularJS direktifi ile dolduracağız.

Direktif oluşturma kalıbı: uygulamaAdi.directive(direktifIsmi, functin() ){ } kalıbı ile olmaktadır.

Direktif içinde restrict’e verdiğimiz E değeri Element anlamına, yani bir DOM elemanı olduğu anlamına gelir. template ile de bu etiketin geçtiği yerde yazdırılacak içerik tanımlanır. return directive ile de direktifin içeriği geri döndürülür.

Merhaba. Ben Uğur GELİŞKEN

Direktiflerde restrict tanımlamasını 3 farklı şekilde yapabiliriz. Bunlar;

Dilerseniz bunların her birini tek bir seferde de kullanabilirsiniz. Yani AE, AC, EC veya AEC gibi. Böylece elementin tüm özelliklerine etki eder. Ek olarak bir de M türü vardır. Bu tür de Comment, yani açıklama satırı olarak verilmiş kodlarda çalışır. Böylece AngularJS’de test tabanlı programlama yapmanıza olana sağlar.

Ayrıca özelleştirilmiş bir element içinde yine özelleştirilmiş direktif tanımlamalarında temel olarak aşağıdaki tanımlamalar bulunur (Listedeki tanımlamalar dışında başka özellikler de bulunmaktadır, ancak şu an temel olarak bunları göreceğiz). Bu tanımlamalarla direktifin özelliklerini ve davranış modelini belirleyebiliriz.

• restrict: E, A, C, M veya bunların türevlerini parametre olarak alır. Böylece elemente mi, attribute’e mi, class’a mı yoksa açıklama satırına mı veya bunlardan birkaçına mı etki edeceği filtrelenir.
• return: Direktifin çalışması sonucunda döndürülecek olan işlemleri belirtir.
• scope: Direktifin kapsama alanını belirler. Eğer kendi faaliyet alanı kullanılacaksa link fonksiyonu içindeki scope’tan alır. Fakat başka kapsama alanları da tanımlanabilir.
• link: Direktifin aktif olması ile birlikte çalışacak olan fonksiyonu tanımlar. Fonksiyon bir takım parametreleri sırasıyla (yani doğru bir sırada yazılmalı) alabilir. Böylelikle erişimler sağlanır. Alacağı parametreler scope, attribute, element ve controller’dır. Aslında bu isimlerle de vermeniz gerekmez. Kısaltılmış da verebilirsiniz. Mesela scp, attr, elem, cont gibi. Fonksiyon içinde de bu parametre isimlerini kullanabilirsiniz. Önemli olan bunların sırasıdır.
• template: Bir HTML içerik üretmenizi sağlar.
• controller: Bir direktif içinde veri alışverişi ve işlem yapılacaksa Controller oluşturmak için kullanılır. Böylece bu tür direktifler ana Controller’dan veya Module’den bağımsız olabilir.
Yazmış olduğumuz bu rolleri uygulamalar içerisinde bolca göreceğiz.

Aşağıdaki örneğimizde kompleks bir yapı ile hem E hem de A kullanacağız. Ayrıca bir elementin içindeki değeri okuyup, tekrar o elementin içinde de innerHTML metodu ile değer yazdıracağız.
Örneğimiz basit bir hali ile devamını oku şeklinde sıkça karşılaştığımız web bileşenidir. Bir cümleyi 25 karakter ile kesecek ve butona tıklandığında da cümlenin tamamını göstereceğiz.

<!DOCTYPE html>
<html>
<head>
   <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
   <meta charset="utf-8">
   <script>
        var uygulama = angular.module("uygulama",[]);
        uygulama.controller("metniAc", function($scope) {
            $scope.hepsiniGoster = function(){
                document.getElementById('1').innerHTML = tamMetin;
            }
        });
        uygulama.directive("soz", function(){
            return {
                restrict: "E",
                link: function(scope, element){
                   tamMetin = element.html();
                }
            }
        });
        uygulama.directive("ozlusoz", function(){
            return {
                restrict: "A",
                link: function(scope, element){
                    element.html(element.html().substring(0, 25).concat("..."));
                }
            }
        });
    </script> 
</head>
<body ng-app="uygulama"  >
  <div id="1" ng-controller="metniAc" >
    <soz ozlusoz >Hata yapmaktan çok korkarsan hiçbir şey yapamazsın - SANJİ</soz>
    <button ng-click="hepsiniGoster()" style="border-radius: 28px; border:none; padding:5px; background-color: #00BFFF">devamını oku</button>
  </div>
</body>
</html>

Yazdığımız kodları inceleyelim…

İlk olarak uygulama adında modülümüzü oluşturduk. Daha sonrasında bu modül içinde metniAc isminde bir Controller, soz etiketi için bir Directive, ozlusoz attribute değeri için de başka bir Directive tanımladık.
metniAc Controller’ı içinde hepsiniGoster şeklinde $scope altında bir fonksiyon oluşturduk. Bu fonksiyon button elementinin ng-click direktifine bind edildi, yani bağlandı. Fonksiyon, id değeri 1 olan DOM elementinin içeriğine innerHTML ile tamMetin değişken değerini yazdıracak. id değeri de div id=”1” ng-controller=”metniAc” şeklinde tanımlanmıştı. Yani bu div kutusunun içeriği hedef alınıyor. Atama yapıldığında div’in içindeki ve button elementleri silinecek, yerine sadece yazı yazdırılacak.

Yeri gelmişken DOM elementlerini de incelediğimizde div’e Controller olarak metniAc modülünün bind edildiğini görebiliriz. div içinde de sozşeklinde bir etiketimiz var. Bu etiket ile adı soz olan (zaten başka bir isim olamazdı, element ile aynı isimde olmalı) direktif otomatik olarak çalışacak. soz direktifini incelediğimizde return ile bir sonuç döndürdüğü görülüyor. Kök fonksiyonunda scope ve element parametreleri yeterli gelmiş. element değeri ile hedeflenmiş olan soz etiketi işaretlenir. .html metodu ile de aynı .innerHTML’de olduğu gibi içeriği hedeflenir. Kök fonksiyonu içinde sadece tamMetin değişkeni tanımlanmış ve bu değişkene element.html; ile soz etiketleri içinde yer alan “Hata yapmaktan çok korkarsan hiçbir şey yapamazsın – SANJİ” metni atanıyor. Bu şekilde, butona tıklanması ile metnin tamamını görüntülemek için gerekli olan değeri saklamış oluyoruz. Aksi halde az önce bahsetmiş olduğumuz kısaltma işlemi ile metni kaybetmiş olacaktık. Ayrıca burada direktiflerin sıralamalarına da dikkat edin. Eğer soz direktifi ozlusoz direktifinden sonra gelseydi (yani kod yazımında yukarıdan aşağıya olan derleme sırası), bu sefer ilk işlemde metin kırpılacağı için tam metin alınıp saklanamazdı. Buna dikkat edelim.

soz etiketinin içinde bir de ozlusoz attribute değeri bulunuyor. ozlusoz attribute’ü için de yine kendi isminde direktif otomatik olarak çalışıyor. Basit birkaç String fonksiyonu ile metin kısaltılıyor. .substring(0,25) ile cümleyi 25 karakter sınırına getiriyoruz. Cümlenin kısaltıldığını belli etmek için de .concat() metodu ile … karakterlerini cümlenin sonuna ekliyoruz. Toplamda 28 karakter oluyor.

Son olarak bir div içinde bir button nesnemiz var. Bu butonun style attribute değeri ile birkaç stil düzenlemesi yapıldı, isterseniz CSS dosyasına alabilirsiniz. Devamını Oku butonuna tıklandığında ng-click direktifi sayesinde hepsiniGoster fonksiyonu çalışacak ve id değeri 1 olan DOM elementi içinde, yani div’in içinde metnin tamamını yazdıracak.

içindeki tüm yazılar silineceği için haliyle soz ve button etiketleri de silinecek.

Sayfa ilk yüklendiğinde:

Butona tıklandığında:

$compile Derleme Servisi ile Türetilen Elementlerle Çalışmak

$compile servisi, Directive veya Controller içindeki bir HTML içeriğini derlememizi sağlar. Daha somut ifade etmek gerekirse, HTML5 sayfası yüklendiğinde AngularJS kodlarının olduğu JS dosyası veya HTML5 içinde script içine gömülüyse çalıştırılır ve derlenir. Fakat bu mantıkla bakıldığında ilk olarak HTML5 sayfası baştan aşağı okunur, sonra AngularJS çalıştırılır. Yani AngularJS çalıştığında HTML5 sayfası üzerinde bir değişiklik yapılmışsa, artık o değişiklik yapılan kısım görmezden gelinir. Bu gibi durumlarda $compile servisi kullanılarak bazı alanlar tekrar derlemeye alınır.

Yapacağımız örneğimizde şöyle bir sorunumuz olacak. Yine bir önceki örneğimizde olduğu gibi bir metin kısaltması yapacağız ve butona tıklandığında tamamını göstereceğiz. Ancak burada farklı olarak butonu doğrudan HTML5 sayfasına yazmaktan ziyade, butonu Directive içinde String olarak tanımlayıp, sözün arkasına ekleyeceğiz. Butona tıklandığında da, yani ng-click direktifiyle de bir Controller tetikletip metni tam göstereceğiz. Az önce dediğimiz derleme sıkıntısı burada yaşanıyor. Butonu sonradan ekleyeceğiz için AngularJS bunu görmeyecektir. Bu nedenle $compile servisini kullanıp eklediğimiz butonu da tekrar AngularJS kapsama alanına çekeceğiz.

Örneğimizde metni kırpma işlemini farklı bir mantıkla yapacağız. Metni iki farklı etikete yayacağız. Özlü sözümüzü soz etiketleri içinde yazdıracağız. Bu etiketlerin arasında da sahibi şeklinde başka bir etiket açıp sözün kime ait olduğunu yazacağız. Bu etiket, daha önce gördüğümüz ng-if direktifi ile kontrol edilecek. Kontrol değişkenin True/False değerlerine göre bu etiketin içeriği görünür olacak veya görünmeyecek. Görünürlüğün değişken parametresini değiştirebilmek için de Directive içinde tanımlayacağımız span etiketleri ile devamını oku şeklinde bir metin oluşturup, bu etikete de ng-click direktifi ekleyerek bir Controller’ı tetikleyeceğiz. Controller içinde de True/False değerlerini her tıklamada sürekli tersi durumu hale getiren basit bir atama işlemi yapacağız.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
        <script>

          var uygulama = angular.module("uygulama",[]);
          uygulama.controller('DevaminiOku', function($scope) {
                $scope.oku = function(){
                    $scope.goster =! $scope.goster;
                }   
          });

          uygulama.directive("ozlusoz", function($compile) {
              var devaminiOkuButonu = "<span ng-click='oku()'> +</span>";
              return{
                     restrict: "A",
                     link: function(scope, element){
                           var eklenecekIcerik = $compile(devaminiOkuButonu)(scope);
                           element.append(eklenecekIcerik);
                      }
              }
       });

      </script>
    </head>
    <body ng-app="uygulama" ng-init="goster=false"  >
       <soz ozlusoz ng-controller="DevaminiOku">Yüzlerce silahla donanmış olsan bile, bazen bir adamın yüreğindeki inanç mızrağına karşı koyamazsın<sahibi ng-if="goster" style="margin-left:10px">Kızıl Bacak Jeff</sahibi></soz>
    </body>
</html>

Yazdığımız kodları inceleyelim…

DOM elementlerinden başlayalım. İlk olarak etiketi içinde ng-app ile uygulama adındaki Module bağlanıyor. ng-init ile de sözün sahibini belirleyen etiketinin ng-if direktifi ile gösterilip gösterilmeyeceğini belirtecek olan goster adındaki Boolean değişkenini tanımlıyoruz. Varsayılan değerini False veriyoruz. Böylece sayfa ilk yüklendiğinde sözün sahibi görünmeyecek.

adında bir kök etiketimiz var. Aslında bu etiketin isminin pek de bir önemi yok, yani başka bir isim de olabilir. Mesela p, div gibi… Bu etiketin içinde bizi ilgilendiren tanımlayıcı değer ozlusoz attribute değeridir. ozlusoz attribute değerine bağlı olan ozlusoz Directive’ini tetikliyoruz. Ayrıca Controller’ın da bu etiket üzerinde çalışmasını sağlamak için ng-controller ile DevaminiOku Controller’ını tanımlıyoruz. (Eğer birden fazla soz etiketi tanımlayacaksanız, body içinde ng-controller tanımlamanız gerekir. Fakat bu sefer de her biri için ayrı ayrı Boolean değişkenleri ve ayrı ayrı Directive’ler oluşturmanız gerekirdi). goster değeri True olursa sahibi etiketinin içi görünür olacak, False olursa görünmeyecek.

İlk olarak ozlusoz direktifine baktığımızda, fonksiyonun $compile parametresi aldığını görüyoruz. Böylece bu fonksiyon içinde $compile servisi kullanılabilecek. var deyimi ile devaminiOkuButonu adında bir değişken tanımlayıp = atama operatörü ile “ ” çift tırnak içerisinde etiketimizi tanımlıyoruz. Etiketimiz; span ng-click=’oku()’ + span şeklinedir. Devamını oku yerine sadece + karakteri ekledik. İsterseniz başka bir şey de yazabilirsiniz. Burada önemli olan ng-click direktifi eklenmesi ve oku() fonksiyonun tetiklenmesi. Sonradan eklenecek olan bu etiket ve direktifi $compile servisi ile tekrar kapsama alanına alacağız.

return kod bloğuna baktığımızda; link kök fonksiyonu içerisinde işlem yapılıyor. Fonksiyon için scope ve element parametreleri yeterli. Burada üç aşamalı işlem yapılıyor. $compile servisine ilk parametre olarak derlenecek metin, ikinci parametresine de kapsama alanı veriliyor. Yine aynı işlemle bir atama yapılıp, bu etiket eklenecekIcerik adlı bir değişkene aktarılıyor. Bu değişken de hedef elementin sonuna append() metodu ile ekleniyor. Yani yazının sonuna derlenmiş olan span ng-click=’oku()’ + span ekleniyor.

+ butonuna tıklandığında çalışan oku fonksiyonunda da goster değerine = operatörü ile yine aynı değerin tersi ! operatörü ile tekrar atanıyor. Eğer değer True ise False, False ise True oluyor. Böylece açılır kapanır bir yapımız oluyor.

Sayfa yüklendiğinde:

+ butonuna tıklandığında:

İçeriği paylaş:
  • facebook
  • twitter

Leave a comment

Yorum