Ağu.20

AngularJS (1.3 / 1.5) Eğitimi: AngularJS ve Bootstrap ile Template Kullanarak Resonsive SPA Uygulaması Örneği

Bu makalemizde yapacağımız SPA uygulamasında AngularJS’yi zaten zorunlu olarak kullanacağız. Ek olarak VIEW tasarımlarını düzgün tasarım ve responsive bir şekilde hazırlamak için Bootstrap kullanacağız. Ek olarak MODEL olarak da bir JSON dosyasından veri okuyacağız.

$routeProvider servisi ile yapacağımız uygulamaların çalışabilmesi için uygulamanın sunucu tarafında host edilmiş olması gerekiyor. Veya lokal sistemde WAMP veya XAMMP programlarla sanal sunucu oluşturulup localhost ile test ediliyor olması gerekir.

SPA Uygulaması Hakkında

Uygulamamız basit bir kişisel web sayfası olacak.

Kök sayfamızın ismi şudur:

• index.html

AngularJS yapılandırması yapmak için de şu iki JS dosyasını kullanacağız:

• app/uygulama.js
• app/rota.js
• app/kontroller.js

Template olarak da şu sayfaları kullanacağız:

• template /anasayfa.html
• template /hakkimda.html
• template /portfolyo.html
• template/iletisim.html

Model için şu dosyayı kullanacağız:

• json/portfolyo.json

Ek olarak bir klasörümüz olacak ve bu klasör içinde tasarım içinde kullanacağımız varlıklar, yani grafikler yer alacak.

• assets
Ek olarak portfolyo.html Template’ini değişken bir sayfa olarak tasarlayacağız. Yani ana sayfa ve iletişim sayfası bilgileri çok değişmeyebilir. Yani ana sayfada basitçe bizi tanıtan bir yazı, bir fotoğraf, sayfalar arası geçiş yapan bir menü ve sosyal medya hesapları ile ilgili linkler olabilir. Portfolyo sayfasında ise sürekli olarak yeni yaptığımız her işi eklemek isteyebiliriz. Nihayetinde değişken bir sayfa olacak ve MODEL olarak bir yerden veri çekmesi gerekecek. Bunun için statik bir JSON dosyası kullanacağız. Aslında en doğrusu; bir PHP dosyasından Veritabanı’na bağlanarak $http.get() servisi ile çekmek (Örneğini IMDB uygulaması yaparken görmüştük). Ancak şu an PHP ile çok çalışmadığımız için işin aslına döneceğiz ve ham üretilmiş JSON’dan okuma yapacağız. İlerleyen konularda PHP ile veritabanına bağlanıp verileri JSON olarak türetmeyi öğreneceksiniz. Ayrıca veritabanına yeni portfolyo eklemek için de bir CMS paneline ihtiyacınız olacak (CMS panelini de kodlamayı öğreneceksiniz). O zaman bu uygulamayı biraz daha geliştirmeniz, SPA’yı daha iyi öğrenmenize faydalı olur.

Ana sayfanın index.html olduğunu biliyoruz. index.html sayfasında ana VIEW’imizi oluşturacağız. ng-app tanımlamasını ve genel Controller’i ng-controller ile bu sayfada belirteceğiz. Sayfamız ilk açıldığında index.html olmasına rağmen, içinde anasayfa.html Template’ini gösterecek. Yani bu sayfayı içe çekeceğiz. Bu sayfa statik olarak bir içerik sunan sayfa olacak. Aynı şekilde iletisim.html sayfası da statik bir Template olacak. Sadece iletişim bilgilerimiz yer alacak. Farklı olarak portfolyo.html dosyasında ise bir servis kullanacak ve dinamik olarak veri çekip, Bootstrap ile verileri düzgün bir şekilde göstereceğiz.

Bütün bunları yaparken de tek bir sayfa üzerinden, yani index.html üzerinden yapacağız. Menüde sayfalar arası geçiş yaparken de hiçbir şekilde sayfa Refresh yapmayacak, yani URL satırında atlama olmayacak.
Sayfalar arası geçişi sağlarken de rota.js dosyasından faydalanacağız. Bu dosya ile bir ngRoute direktifi tanımlayacağız ve Template değişikliklerinde hangi sayfalar için hangi Controller dosyasının otomatik olarak çalıştırılacağı belirtilir.

Dosyaların ve Dizinlerin Oluşturulması

Adım adım sayfalarımızı hazırlıyoruz. Farklı olarak yeni teknikler göreceğiz yerlerde açıklamalar Comment satırları ile ( /* */ ) kodlar içinde gösterilecektir ve açıklanacaktır.

app/uygulama.js

var ugurgelisken = angular.module('ugurgelisken', ['ngRoute']);

Uygulama için Module tanımlaması yapıyoruz. Ancak burada ngRoute direktifinin de eklendiğine dikkat edin!

app/rota.js

ugurgelisken.config(function($routeProvider) {
$routeProvider
    // İNDEX
    .when('/', {
        templateUrl : 'template/anasayfa.html',
        controller  : 'anasayfaCtrl'
    })
	
    // ANA SAYFA
    .when('/anasayfa', {
        templateUrl : 'template/anasayfa.html',
        : 'anasayfaCtrl'
    })
		
    // HAKKIMDA
    .when('/hakkimda', {
        templateUrl : 'template/hakkimda.html',
        controller  : 'hakkimdaCtrl'
    })

    // PORTFOLYO
    .when('/portfolyo', {
        templateUrl : 'template/portfolyo.html',
        controller  : 'portfolyoCtrl'
    })

    // İLETİŞİM
    .when('/iletisim', {
        templateUrl : 'template/iletisim.html',
         controller  : 'iletisimCtrl'
    });
});

app/kontroller.js

ugurgelisken.controller('anasayfaCtrl', function($scope) {
	 $scope.baslik = 'Uğur GELİŞKEN.com';
	$scope.resim = 'assets/ugurgelisken.jpg';
	$scope.icerik = 'Merhaba sevgili okur. Aşağıdaki sosyal medya hesaplarıma ait ikonlara tıklayarak bana ulaşabilirsiniz.';	
	$scope.facebookURL = 'https://www.facebook.com/UgurGELISKEN';
	$scope.linkedinURL = 'https://tr.linkedin.com/in/uğur-gelişken-53007361';
});

ugurgelisken.controller('hakkimdaCtrl', function($scope) {
	$scope.baslik = 'HAKKIMDA';
	$scope.resim = 'assets/ugurgelisken.jpg';
	$scope.icerik = '1983 doğumlu Uğur GELİŞKEN, yayınlamış olduğu eserler, makaleler ve yaptığı projelerle 2013/2014/2015 yıllarında Adobe Community Professional programında, 9 farklı alanda uzmanlık seviyesi ile (Web Design, Graphic Design, Print Design, Digital Publishing, eLearning, Web Application Development, Mobile Application Development, Mobile Flash Gaming, Gamification) Adobe Topluluk Uzmanı (ACP) olarak seçildi. Şu anda IT Sorumlusu olarak iş hayatına devam etmekte, okurlarına özel eğitimler vermekte, yazarlar için danışmanlık yapmakta ve Mobil Programlama / Oyun Geliştirme alanlarında kendini geliştirmeye devam etmektedir. Yazar ve yeni projeleri hakkında daha detaylı bilgi almak için www.ugurgelisken.com adresini ziyaret edebilirsiniz.';	
});

ugurgelisken.controller('portfolyoCtrl', function($scope,$http) {
	$scope.baslik = 'PORTFOLYO';
	$scope.icerik = 'Bu kitaptan önce, en son hazırlamış olduğum iki kitabı aşağıda görebilirsiniz.';
	$http.get("json/portfolyo.json")
                .success(function(response) {
                $scope.sonuc = response;
           });
});

ugurgelisken.controller('iletisimCtrl', function($scope) {
	$scope.baslik = 'İLETİŞİM';
	$scope.icerik = 'Sorularınız varsa, e-mail adresimden bana yazabilirsiniz.';	
	$scope.email = 'ugurgelisken@gmail.com';
});

ugurgelisken.directive('activeLink', function () {
    return {
        link: function (scope, element, attrs) {
            element.find('.nav a').on('click', function () {
                angular.element(this)
                    .parent().siblings('.active')
                    .removeClass('active');
                angular.element(this)
                    .parent()
                    .addClass('active');
            });
        }
    };
});

Burada yer alan Controller’lar, rota.js’deki tanımlamalara göre otomatik olarak çalıştırılacak. Her bir Controller, $scope altında değişkenlere değerler gönderiyor. rota.js sayesinde index.html içindeki ng-wiev alanına yüklenen sayfalardaki direktif alanlarına değerler yazdırılıyor. Ek olarak navigasyon menüde aktif olan butonun zeminini belirtmek için bir Directive tanımladık, bunun açıklamasını da az sonra yapacağız.

Diğer Controller’lardan farklı olarak Portfolyo için bir $http servisi kullanıp JSON dosyasından verileri çekerek sonuc değişkenine atadık. Bununla da ng-repeat döngüsünü kullanıp verileri sıralayacağız.

index.html

<!DOCTYPE html>
<html ng-app="ugurgelisken" >

<head>

  <title>UğurGELİŞKEN.com</title>
  <meta charset="utf-8" />

  <!-- FRAMEWORK'ler -->
  <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-route.js"></script>

  <!-- SAYFA YAPILANDIRICILARI -->
  <script src="app/uygulama.js"></script>
  <script src="app/kontroller.js"></script>
  <script src="app/rota.js"></script>

</head>

<body>
  <nav class="navbar-collapse navbar-inverse" active-link>
    <div class="container-fluid">
      <div class="navbar-header">
        <button type="button" class="navbar-toggle" data-toggle="collapse" 
data-target="#menu">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" href="#anasayfa" >Uğur GELİŞKEN</a>
      </div>
      <div class="collapse navbar-collapse" id="menu" >
        <ul class="nav navbar-nav">
          <li><a href="#hakkimda">Hakkımda</a></li>
          <li><a href="#portfolyo">Portfolyo</a></li>
          <li><a href="#iletisim">İletişim</a></li>
        </ul>
      </div>
    </div>
  </nav>

  <!-- İÇERİKLERİN GÖSTERİLECEĞİ ALAN -->
  <div class="container">
    <div ng-view></div>
  </div>

</body>
</html>

index.html’de dikkatinizi çekmek istediğim birkaç nokta var. Bunlar;

nav ile sayfa için navigasyon menü yapıyorduk. Menüye tıkladığımızda hangi sayfaya gidersek o sayfada o butonun arkası değişik bir renk alır, arka zemini belli olması için de active attribute değerini hangi buton için ise li etiketine veriyoruz. Normalde bu active attribute değerini ya PHP ile ya da başka bir sistemle değiştirmeniz gerektiğini, hangi sayfada ise ona atamanız gerekir. Şu an index.html içinden çıkamadığımız için active atama sistemini kontroller.js içinde yer alan activeLink isimli Directive ile yapıyoruz. Hangi eleman tıklanmışsa ona active attribute değerini atıyor ve diğerlerinden de kaldırıyor. Aslında zorunlu bir çalışma değil ama bu tekniği de görmenizi istedim.

Diğer husus ise yine navigasyon bar içinde yer alan butonların href özelliği. Aynı sayfada kalmak için # hash ataması yapıyoruz. Bu hash atamaları da rota.js içinden $routeProvider ile okunuyor. when özelliği ile URL satırında, / işaretinden sonra hangi değerin geldiğine bakılıyor. Gelen değere göre bir karşılaştırma yapılıp templateURL ile hangi sayfanın çekileceği, controller ile de hangi Controller’ın çalıştırılacağı belirtiliyor.

template /anasayfa.html

<h3>{{baslik}}</h3>
<p>{{icerik}}</p>
<a ng-href="{{facebookURL}}"><img src="assets/facebook.png"</a>
<a ng-href="{{linkedinURL}}"><img src="assets/linkedin.png"</a>

template /hakkimda.html

<br>
<div>
    <div class="row">
        <div class="col-sm-4 col-sm-offset-8"><div class="well well-sm"> 
                <b>{{baslik}}</b></div></div>
        </div>
        <div class="row">
    <div class="col-sm-3"><img ng-src="{{resim}}" class="img-rounded" width="150" height="150"></div>
        <div class="col-sm-9">{{icerik}}</div>
    </div>
</div>

template /iletisim.html

<br>
<div>
    <div class="row">
        <div class="col-sm-4 col-sm-offset-8"><div class="well well-sm">         
                <b>{{baslik}}</b></div>
        </div>
    </div>
    <p>{{icerik}}</p>
    <a href="mailto:{{email}}" >{{email}}</a>
</div>

json/portfolyo.json

{"kitaplarim":[
    {"isim":"Mobil Oyun Tasarimi ve Programlama", "kapakResmiURL":"assets/kapak1.jpg"},
    {"isim":"Android Porgramlama", "kapakResmiURL":"assets/kapak2.jpg"}
]}

Burada kitaplarim isminde bir Object tanımlanıyor (gerçi nesnenin ismi pek farketmiyor) ve içinde kitabın ismi ve kitabın kapak resmi bilgilerini taşıyoruz. 2 adet verimiz var. Bunları portfolyo sayfasında yazdırıyoruz.

template /portfolyo.html

<br>
<div class="row">
  <div class="col-sm-4 col-sm-offset-8">
    <div class="well well-sm"><b>{{baslik}}</b></div>
  </div>
</div>
<div>
  <p>{{icerik}} </p>
      <div style="float:left">
        <div ng-repeat="kitap in sonuc">
          <div ng-repeat="(id, degerler) in kitap">
            <div><b>{{id+1}} - {{degerler.isim}}</b></div>
            <div><img ng-src="{{degerler.kapakResmiURL}}" /></div>
          </div>
        </div>
      </div>
</div>

portfolyo.json dosyası içinden kitap verileri okunuyor ve ng-repeat ile listeleniyor.

SPA Uygulamasını Test Etmek

Sayfaları sırası ile açıp sonuçlarına bakalım. Şu an testi WAMP Server ile local sistemde SPA klasörü içinde yapıyorum. Test ederken index.html sayfası içeriği tarayıcıda hiç değişmeyecektir. Yani hangi sayfada bakarsanız bakın sayfa kodu aynıdır. Sayfalar arası geçiş yaparken de URL satırlarında hash değerlerine bakmayı unutmayın.

Aşağıda, ana sayfa görülmektedir:

Sayfayı daralttığımızda mobil görünüme geçecektir.

Hakkımda sayfası:

Portfolyo sayfası:

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

Leave a comment

Yorum