[AngularJS]建立Directives

  • 2748
  • 0
  • 2014-07-15

摘要:[AngularJS]建立Directives

[AngularJS]建立Directives


Directives 概述

Directive 就像是Template。

Directives分為兩種:

  • Element Directive
    • 使用場景,當Directive當作UI項目使用時。

  • Attribute Directive
    • 使用場景,當Directive當作行為使用時,例如:tooltip。


為什麼要使用 Directive

  • 將html代碼簡化
  • 一大串的html,其本質上是有意義的,但不易讀。若以Directive 來顯示將能更容易讀出其功能性。
  • 重用代碼


如何建立 Directive

  • 新增一個 html 頁面。
  • 將要抽離的 html 代碼部分,搬移到 新的html。
  • 於js 內新增directive。如下圖


珠寶商店

現在要使用Directive來簡化代碼。

  • 將 PanelController包裝成一個新的Directive,於 js 內 建立

    //html裡Element使用時是用product-panels (中間字段有大寫前面加上'-' )
    app.directive('productPanels',function()
    {
        return {
            restrict: 'E',
            templateUrl: 'productPanels.html',
            //將panelController當作controller
            controller:this.panelController,
            //使用別名'panel'
            controllerAs:'panel'
        };
    });
    //原 panelController
    this.panelController=function()
    {
        //controller內的屬性一有變動就會自動檢查html與controller有綁定方法的元素
        //所以只需 將html 元素 與 controll綁定就好 不用擔心何時觸發
        //這部分 是否有人可以幫忙補充?
        this.tabIndex = 1;
        this.selectTab = function(setTab) {
            this.tabIndex = setTab;
        }
    
        //判斷選擇的頁面 是否 等於 該tabIndex
        this.isSelected = function(checkTab){
            return this.tabIndex === checkTab;
        };
    }
    
  • 將原本的PanelController包覆的html代碼抽離到productPanles.html(新建)

    • productPanles.html

      <!--原本PanelController 包含的範圍 -->
      <!--現在將不用ng-controller,因為已經於Directive內宣告完畢,並使用別名panel -->
      <section>

          <ul class="nav nav-pills">
              <!--active:panel.tab===1 的意思是 若 panel.tab===1 時 激活(顯示) -->
              <li ng-class={active:panel.tabIndex===1}>
                  <a href ng-click="panel.selectTab(1)">Description</a>
              </li>
      
              <li ng-class="{active:panel.tabIndex===2}">
                  <a href ng-click="panel.selectTab(2)">Price</a>
              </li>
              <li ng-class="{active:panel.tabIndex===3}">
                  <a href ng-click="panel.selectTab(3)">Reviews</a>
              </li>
              </div>
          </ul>
          <div class="container">
      
              //呼叫controller的方法 判斷資訊是否 可顯示
              <div class="panel" ng-show="panel.isSelected(1)">
                  <h4>Description</h4>
      
                  <p>{{product.description}}</p>
              </div>
      
              <div class="panel" ng-show="panel.isSelected(2)">
                  <h4>Price</h4>          
                  <p>{{product.price}}</p>
              </div>
              <div class="panel" ng-show="panel.isSelected(3)">
                  <h4>Reviews</h4>
                  <img ng-src="{{product.img}}"/>

              </div>
          </div>
      </section>
      
  • 於 Index 使用:

    • Index.html

      <product-panels></product-panels>
      


經以上程序後,完整代碼如下:

  • Index.html

    <!DOCTYPE html>
    <html ng-app="store">
    <head lang="en">
        <script type="text/javascript" src="angular.min.js"></script>
        

        <script type="text/javascript" src="app.js"></script>
        <link rel="stylesheet" href="bootstrap.css"/>
        <link rel="stylesheet" href="bootstrap-theme.css">
        <link rel="stylesheet" href="style.css">
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body ng-controller="StoreController as store">
    
    <p>
    <ul class="list-group">

        <li class="list-group-item"
            ng-repeat="product in store.products | orderBy:'name' "> 

            <h3>
                {{product.name | uppercase}}
                <h3>
                    {{product.price | currency }}
                </h3>
            </h3>
    
            <p>{{product.date | date:'MM/dd/yyyy'}}</p>
    
            <p><img ng-src="{{product.img}}"></p>
    
           //新增 一個 controller //新增一個 PanelController 來控制顯示寶石資訊細節的 table
            <product-panels></product-panels>
    
              <section>
                 <blockquote ng-repeat="review in product.reviews">
                     <h3>
                         <b>Stars: {{review.stars}}</b>

                         {{review.body}} 

                         <cite>by: {{review.author}}</cite>
                         <cite>Description:{{review.body}}</cite>
                     </h3>
                 </blockquote>
             </section>
             <!-- 留言板-->
            <!--新增 ReviewController-->
            <!--novalidate 不須被驗證-->
            <!--在form標籤中我們只需要取得$valid 驗證是否執行reviewCtrl.addReview(product)-->
            <form name="reviewForm"
                  class="form-horizontal"
                  ng-controller="ReviewController as reviewCtrl"
                  ng-submit="reviewForm.$valid && reviewCtrl.addReview(product)"
                  novalidate
                    >
                <div class="form-group">
                    <div class="controls">
                        <blockquote>
                            <b>Stars: {{ reviewCtrl.review.stars}}</b>
                            {{ reviewCtrl.review.body}}
                            <cite>by: {{ reviewCtrl.review.author}}</cite>
                        </blockquote>
                    </div>
                </div>
    
                <div class="form-group">
                    <section>
                        <!--<label>stars:</label>-->
                        <label class="control-label">Stars</label>
    
                        <!-- required 需要被驗證-->
                        <div class="controls">
                            <select ng-model="reviewCtrl.review.stars" required>
                                <option value="1">1 star</option>
                                <option value="2">2 stars</option>
                                <option value="3">3 stars</option>
                                <option value="4">4 stars</option>
                                <option value="5">5 stars</option>
                            </select>
                        </div>
                    </section>
                </div>
    
                <div class="form-group">
                    <label class="control-label">Description</label>
    
                    <div class="controls">
    
                        <!-- required 需要被驗證-->
                        <textarea ng-model="reviewCtrl.review.body"
                                  placeholder="Typing Description…"
                                  required></textarea>
                    </div>
                </div>
    
                <div class="form-group">
                    <label class="control-label">Author</label>
    
                    <div class="controls">
    
                        <!-- required 需要被驗證-->
                        <input ng-model="reviewCtrl.review.author"
                               type="email"
                               placeholder="Typing email…"
                               required/>
                    </div>
                </div>
    
                <div class="form-group">
                    <div class="controls">
    
                        //若 驗證失敗 則disabled
                        <input type="submit"
                               ng-disabled="!reviewForm.$valid"
                               class="btn btn-primary"
                               value="Submit"/>

                    </div>
                </div>
            </form>
        </li>
        

    </ul>
    </p>
    </body>
    </html>
    
  • productPanles.html

    <!--原本PanelController 包含的範圍 -->
    <!--現在將不用ng-controller,因為已經於Directive內宣告完畢,並使用別名panel -->
    <section>

        <ul class="nav nav-pills">
            <!--active:panel.tab===1 的意思是 若 panel.tab===1 時 激活(顯示) -->
            <li ng-class={active:panel.tabIndex===1}>
                <a href ng-click="panel.selectTab(1)">Description</a>
            </li>
    
            <li ng-class="{active:panel.tabIndex===2}">
                <a href ng-click="panel.selectTab(2)">Price</a>
            </li>
            <li ng-class="{active:panel.tabIndex===3}">
                <a href ng-click="panel.selectTab(3)">Reviews</a>
            </li>
            </div>
        </ul>
        <div class="container">
    
            //呼叫controller的方法 判斷資訊是否 可顯示
            <div class="panel" ng-show="panel.isSelected(1)">
                <h4>Description</h4>
    
                <p>{{product.description}}</p>
            </div>
    
            <div class="panel" ng-show="panel.isSelected(2)">
                <h4>Price</h4>
                <p>{{product.price}}</p>
            </div>
            <div class="panel" ng-show="panel.isSelected(3)">
                <h4>Reviews</h4>
                <img ng-src="{{product.img}}"/>

            </div>
        </div>
    </section>
    
  • js

    //建構
    AppConstructor()
    
    //將你的JavaScipt 放在一個閉包裡是一個好的習慣
    function AppConstructor()
    {
        app = angular.module('store', [ ]);
    
        app.controller('StoreController', function()
        {
            this.products=gems;
        });
    
        app.controller("ReviewController",this.reviewController );
    
        app.directive('productTitle',function()
        {
            return {
            restrict: 'E',
            templateUrl: 'product-title.html'};
        });
    
    //html的Element在使用時是用product-panels (中間字段有大寫前面加上'-' )
        app.directive('productPanels',function()
        {
            return {
                restrict: 'E',
                templateUrl: 'productPanels.html',
                //將panelController當作controller
                controller:this.panelController,
                //使用別名'panel'
                controllerAs:'panel'
            };
        });
        //原 panelController
        this.panelController=function()
        {
            //controller內的屬性一有變動就會自動檢查html與controller有綁定方法的元素
            //所以只需 將html 元素 與 controll綁定就好 不用擔心何時觸發
            //這部分 是否有人可以幫忙補充?
            this.tabIndex = 1;
            this.selectTab = function(setTab) {
                this.tabIndex = setTab;
            }
    
            //判斷選擇的頁面 是否 等於 該tabIndex
            this.isSelected = function(checkTab){
                return this.tabIndex === checkTab;
            };
        }
    
    
        var gems=[
            {
                name:'Dodecahedron',
                price:5.95,
                description:'Some gems have hidden qualities beyond their luster,beyond their shine...Dodeca is one of those gems.',
                date:1388123412323,
                img:'http://content.screencast.com/users/BensonLan/folders/Jing/media/3244f630-438f-42ea-9f1f-cd8645b3f024/2014-07-10_1510.png',
    
                //新增回覆屬性
                reviews:[
                    new Review(3,'I love this product!','I love this product!','Benson@hotmail.com')                ,
                    new Review(5,'good for you!','tom@yahoo.com.tw')
    
                ]
            },
            {
                name:'pentagonalGem',
                price:5,
                description:'Some gems have hidden qualities beyond their luster,beyond their shine...Dodeca is one of those gems.',
                date:1288123412323,
                img:'http://content.screencast.com/users/BensonLan/folders/Jing/media/f6c03fe4-6d0a-421f-904e-9ad3890ed755/2014-07-10_1511.png',
                reviews:[
                    new Review(1,'good for you!','joe@yahoo.com.tw')
                    ,
                    new Review(5,'cheap!','tom@yahoo.com.tw')
                ]
            },
            {
                name:'redGem',
                price:3.85,
                description:'Red.',
                date:1299123412323,
                img:'http://content.screencast.com/users/BensonLan/folders/Jing/media/ea8c267d-032d-4d54-b9a4-cb5861e2c7ca/2014-07-10_1512.png',
                reviews:[
                    new Review(4,'well done!','amber@yahoo.com.tw')
                    ,
                    new Review(5,'pretty!','mark@yahoo.com.tw')
    
                ]
    
            }
            ,
            {
                name:'bigGem',
                price:3.20,
                description:'big',
                date:132123412323,
                img:' http://content.screencast.com/users/BensonLan/folders/Jing/media/c8d1f866-8cc0-4475-84e5-b671176367e2/2014-07-10_1512.png',
                reviews:[
                    new Review(3,'oh my god!','san@yahoo.com.tw')
                    ,
                    new Review(2,'i want it!','qq@yahoo.com.tw')
                ]
            }
        ]
    
    
    
    
        this.reviewController=   function(){
    
            //init
            this.review =new Review(1,'','');
    
            //when Submit doing
            this.addReview=function(product) {
                product.reviews.push(this.review);
                this.review =new Review(1,'','');
            };
        }
    
        function Review(inputStars,inputBody,inputAuthor)
            {
                this.stars=inputStars;
                this.body=inputBody
                this.author=inputAuthor
            }
    }
    


Result




By-藍小伙