본문 바로가기

Javascript/Angular.js

CodeSchool Angular.js Level2

첫시간은 filter다.


Angular.js에서는 필터로 통화기호 표시도 해주고, 리스트인 경우 정렬도 해준다. uppercase로 대문자로 변환도 해주고, limitTo로 글자 수 제한도 걸 수 있다. pipe 라인으로 지정할 수 있다. 값이 이 pipe라인을 거치면서 필터링된다고 생각하면 될듯... 이거 만든 사람 천잰데??



<!DOCTYPE html>

<html ng-app="gemStore">

  <head>

    <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />

    <script type="text/javascript" src="angular.min.js"></script>

    <script type="text/javascript" src="app.js"></script>

  </head>

  <body class="container" ng-controller="StoreController as store">

    <div class="product row" ng-repeat="product in store.products">

      <h3>

        {{product.name}}

        <em class="pull-right">{{product.price | currency}}</em>

      </h3>

    </div>

  </body>

</html>

이런식으로.. 앞에 부턴 $ 표시를 안 써도 된다!


2단계는 이미지 보여주기!

(function() {

  var app = angular.module('gemStore', []);


  app.controller('StoreController', function(){

    this.products = gems;

  });


  var gems = [{

      name: 'Azurite',

      description: "Some gems have hidden qualities beyond their luster, beyond their shine... Azurite is one of those gems.",

      shine: 8,

      price: 110.50,

      rarity: 7,

      color: '#CCC',

      faces: 14,

      images: [

        "images/gem-02.gif",

        "images/gem-05.gif",

        "images/gem-09.gif"

      ],

      reviews: [{

        stars: 5,

        body: "I love this gem!",

        author: "joe@example.org",

        createdOn: 1397490980837

      }, {

        stars: 1,

        body: "This gem sucks.",

        author: "tim@example.org",

        createdOn: 1397490980837

      }]

    }, {

      name: 'Bloodstone',

      description: "Origin of the Bloodstone is unknown, hence its low value. It has a very high shine and 12 sides, however.",

      shine: 9,

      price: 22.90,

      rarity: 6,

      color: '#EEE',

      faces: 12,

      images: [

        "images/gem-01.gif",

        "images/gem-03.gif",

        "images/gem-04.gif"

      ],

      reviews: [{

        stars: 3,

        body: "I think this gem was just OK, could honestly use more shine, IMO.",

        author: "JimmyDean@example.org",

        createdOn: 1397490980837

      }, {

        stars: 4,

        body: "Any gem with 12 faces is for me!",

        author: "gemsRock@example.org",

        createdOn: 1397490980837

      }]

    }, {

      name: 'Zircon',

      description: "Zircon is our most coveted and sought after gem. You will pay much to be the proud owner of this gorgeous and high shine gem.",

      shine: 70,

      price: 1100,

      rarity: 2,

      color: '#000',

      faces: 6,

      images: [

        "images/gem-06.gif",

        "images/gem-07.gif",

        "images/gem-10.gif"

      ],

      reviews: [{

        stars: 1,

        body: "This gem is WAY too expensive for its rarity value.",

        author: "turtleguyy@example.org",

        createdOn: 1397490980837

      }, {

        stars: 1,

        body: "BBW: High Shine != High Quality.",

        author: "LouisW407@example.org",

        createdOn: 1397490980837

      }, {

        stars: 1,

        body: "Don't waste your rubles!",

        author: "nat@example.org",

        createdOn: 1397490980837

      }]

    }];

})();

이렇게 이미지를 추가했다.


<!DOCTYPE html>

<html ng-app="gemStore">

  <head>

    <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />

    <script type="text/javascript" src="angular.min.js"></script>

    <script type="text/javascript" src="app.js"></script>

  </head>

  <body ng-controller="StoreController as store">

    <!--  Products Container  -->

    <div class="list-group">

      <!--  Product Container  -->

      <div class="list-group-item" ng-repeat="product in store.products">

        <h3>

          {{product.name}}

          <em class="pull-right">{{product.price | currency}}</em>

        </h3>

        <!-- Image Gallery  -->

        <div class="gallery">

          <img ng-src="{{product.images[0]}}" />

        </div>

      </div>

    </div>

  </body>

</html>

이미지인 경우 ng-src를 써야한다. 그냥 src를 쓰면 당연히 안된다. 그리고 이때는 중괄호 {{}} 와 함께 써줘야한다는게 주의할 점!

만약에 해당 이미지들을 모두 보여주고 싶다면?

<li ng-repeat="image in product.images" class="small-image pull-left thumbnail" >

<img ng-src="{{image}}" />

 </li>

loop 안에서 또 loop 돌리면 된다. 아주 간단하다.

그런데 images 가 있을때에만 해당 div를 보여주고 싶다면?

<div class="gallery" ng-show="product.images.length">

배열 유무는 length로 체크한다. 




이제부터 본격적인 사용법이 나온다. 

좀 더 인터랙티브한 페이지를 만들기 위한 방법들을 알려준다.


<section>

  <ul class="nav nav-pills">

    <li><a href ng-click="tab = 1">no1</a></li>

    <li><a href ng-click="tab = 2">no2</a></li>

    <li><a href ng-click="tab = 3">no3</a></li>

  </ul>

  {{tab}}

</section>  

이렇게 해놓으면 클릭할때마다 tab의 값이 바뀌고 바로 화면에 적용된다. 다른거 할 필요 없이 이것만으로 tab의 값이 변한다고! 

이렇게 편할수가!?


그리고 이 tab을 클릭할때마다 tab 값에 따라 패널을 show해줘야 하는 경우가 있을 것이다. 그때는


<div class="pannel" ng-show="tab === 1">

  <h1>pannel 1</h1>

</div>

<div class="pannel" ng-show="tab === 2">

  <h1>pannel 2</h1>

</div>

<div class="pannel" ng-show="tab === 3">

  <h1>pannel 3</h1>

</div>

보아라. 이렇게 하면 pannel 클래스 div가 tab 값에 따라 보였다 안보였다 한다. 그렇다면, 처음에는 tab값이 없으므로 아무 패널도 나오지 않을 것이다. 하지만 기본값으로 1번 패널을 보여줘야 하는 경우라면...? ng-init 을 이용하면 된다.


<section ng-init="tab=1">

  <ul class="nav nav-pills">

    <li><a href ng-click="tab = 1">no1</a></li>

    <li><a href ng-click="tab = 2">no2</a></li>

    <li><a href ng-click="tab = 3">no3</a></li>

  </ul>

  {{tab}}

</section>  


이렇게 말이다. 그러면 tab 디폴트값은 1이 되고, 패널1이 디폴트로 화면에 보여지게 된다.


이제 거의 다 되었다. 그런데 tab을 클릭했을때 해당 li의 클래스에 엑티브 클래스를 줘야하는 상황이 있을 것이다. 이때는 어찌해야하나?


<section ng-init="tab=1">

  <ul class="nav nav-pills">

    <li ng-class="{ active:tab === 1 }">

<a href ng-click="tab = 1">no1</a>

    </li>

    <li ng-class="{ active:tab === 2 }">

<a href ng-click="tab = 2">no2</a>

    </li>

    <li ng-class="{ active:tab === 3 }">

<a href ng-click="tab = 3">no3</a>

    </li>

  </ul>

  {{tab}}

</section>

이렇게 하면 된다! 허참 기가 막힌듯!


하지만.. 이렇게 하면 html 소스와 Angular.js 소스가 섞여 있어서 보기에 좋지 않다. 

유지보수도 힘들거고..

그래서 이걸 따로 분리하는 작업을 해주는게 좋다.


1. 컨트롤러 생성


app.js

app.controller('TabController', function(){

// ng-init

this.tab = 1;


// ng-click

this.selectTab = function(setTab){

this.tab = setTab;

};


// selected 여부

this.isSelected = function(checkTab){

return this.tab === checkTab;

};

 });


index.html

<section ng-controller="PanelController as panel">

  <ul class="nav nav-pills">

<li ng-class="{ active: panel.isSelected(1) }">

<a href ng-click="panel.selectTab(1)">no1</a>

</li>

<li ng-class="{ active: panel.isSelected(2) }">

<a href ng-click="panel.selectTab(2)">no2</a>

</li>

<li ng-class="{ active: panel.isSelected(3) }">

<a href ng-click="panel.selectTab(3)">no3</a>

</li>

  </ul>

  {{tab}}


<div class="pannel" ng-show="panel.isSelected(1)">

  <h1>pannel 1</h1>

</div>

<div class="pannel" ng-show="panel.isSelected(2)">

  <h1>pannel 2</h1>

</div>

<div class="pannel" ng-show="panel.isSelected(3)">

  <h1>pannel 3</h1>

</div>

</section>


두둥.. 이렇게 하면 한결(?) 직관적이다. 



응용해보자

app.js

app.controller('GalleryController', function(){

    this.current = 0;

    this.setCurrent = function(newGallery){

      this.current = newGallery || 0; 

    };

  });

갤러리 컨트롤러를 추가한다. 

default parameter 셋팅은 여기 참고

https://googlechrome.github.io/samples/default-parameters-es6/


그리고 html은

<!DOCTYPE html>

<html ng-app="gemStore">

  <head>

    <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />

    <script type="text/javascript" src="angular.min.js"></script>

    <script type="text/javascript" src="app.js"></script>

  </head>

  <body class="list-group" ng-controller="StoreController as store">

    <header>

      <h1 class="text-center">Flatlander Crafted Gems</h1>

      <h2 class="text-center">– an Angular store –</h2>

    </header>

    <div class="list-group-item" ng-repeat="product in store.products">

      <h3>

        {{product.name}}

        <em class="pull-right">{{product.price | currency}}</em>

      </h3>


      <!-- Image Gallery  -->

      <div class='gallery' ng-show="product.images.length" ng-controller="GalleryController as gallery">

        <img ng-src="{{ product.images[ gallery.current ] }}" />

        <ul class="list-inline thumbs">

          <li class="thumbnail" ng-repeat="image in product.images">

            <img ng-src="{{image}}" />

          </li>

        </ul>

      </div>


      <section class="tab" ng-controller="TabController as tab">

        <ul class="nav nav-pills">

          <li ng-class="{ active: tab.isSet(1) }">

            <a href ng-click="tab.setTab(1)">Description</a></li>

          <li ng-class="{ active: tab.isSet(2) }">

            <a href ng-click="tab.setTab(2)">Specs</a></li>

          <li ng-class="{ active: tab.isSet(3) }">

            <a href ng-click="tab.setTab(3)">Reviews</a></li>

        </ul>

        <div ng-show="tab.isSet(1)">

          <h4>Description</h4>

          <blockquote>{{product.description}}</blockquote>

        </div>

        <div ng-show="tab.isSet(2)">

          <h4>Specs</h4>

          <blockquote>Shine: {{product.shine}}</blockquote>

        </div>

        <div ng-show="tab.isSet(3)">

          <h4>Reviews</h4>

        </div>

      </section>

    </div>

  </body>

</html>

이렇게 쓸 수 있다. 

구조를 보면 컨트롤러 안에서 컨트롤러를 또 쓸 수 있다는 걸 알 수 있다. 

갱장히 유연하다고 볼 수 있겠다.


여기까지 하면 레벨2 완료~






* 소스는 모두 http://campus.codeschool.com 에서 가져온 겁니다.

'Javascript > Angular.js' 카테고리의 다른 글

CodeSchool Angular.js Level5  (0) 2017.03.10
CodeSchool Angular.js Level4  (0) 2017.03.09
CodeSchool Angular.js Level3  (0) 2017.03.07
CodeSchool Angular.js Level1  (0) 2017.02.27