[AngularJs]珠寶商店-新增留言板功能及驗證機制說明

  • 1244
  • 0

摘要:[AngularJs]新增留言板功能及驗證機制說明

[AngularJs]新增留言板功能及驗證機制說明


概述

本章,將介紹新的Directives,並不贅續說明直接以範例說明。

  • ng-model

    • 這個Directive 提供值綁定功能。
  • validations

    • 本章將說明驗證的機制。
    • 驗證將觸發 classes變更並對應到css,默認匹配幾個 css 項目(名稱對應上,即可自訂義內容),以凸顯某驗證機制的顯示。


寶石商店

新任務,在每個寶石資訊中加入提供者留言版功能。

  • 於js中新增回覆訊息類別。

    function Review(inputStars,inputBody,inputAuthor)
    {
        this.stars=inputStars;
        this.body=inputBody
        this.author=inputAuthor
    }
    


  • 修正js中gems對象,所帶的參數,給一些預設的留言訊息。

    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')
        ]
    }
    


  • 新增一個controller,當作流言版的控制器。並定義當html按下Submit時的邏輯。

    //留言版的controller
    app.controller("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,'','');
        };
    })
    


  • html前端,新增一個留言版的form 於珠寶項目中

    • novalidate(不須驗證)、required(需要驗證的項目,當屬性改變時檢查及更改form.$valid狀態並通知 )

    -

       <!-- 留言板-->
        <!--新增 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>
    


  • 新增style.css 標示驗證狀態改變時,required 項目 顯示的顏色不同

    • ng-invalid.ng-dirty
      • 當無效時會匹配到css的名稱
    • ng-valid.ng-dirty
      • 當有效時會匹配到css的名稱
    • ng-pristine.ng-invalid

      • 當項目初始的匹配到css的名稱
      .ng-invalid.ng-dirty {
          border-color: #FA787E;
      }
      
      .ng-valid.ng-dirty {
      border-color: #78FA89;
      }
      
      .ng-pristine.ng-invalid
      {
          border-color: #333333;
      }
      


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

  • js code

    //建構
    AppConstructor()
    
    //將你的JavaScipt 放在一個閉包裡是一個好的習慣
    function AppConstructor()
    {
        app = angular.module('store', [ ]);
    
        app.controller('StoreController', function()
        {
            this.products=gems;
        });
        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')
                ]
            }
        ]
    
        //新增一個 PanelController 來控制顯示寶石資訊細節的 table
        app.controller('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;
            };
        });
    
        //留言版的controller
        app.controller("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
            }
    }
    


  • html code

    <!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}}
                <em class="pull-right">
                    {{product.price | currency }}
                </em>
            </h3>
    
            <p>{{product.date | date:'MM/dd/yyyy'}}</p>
    
            <p><img ng-src="{{product.img}}"></p>
    
            //新增 一個 controller //新增一個 PanelController 來控制顯示寶石資訊細節的 table
            <section ng-controller="PanelController as panel">

                <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>
            <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>
    


  • css

    .ng-invalid.ng-dirty {
        border-color: #FA787E;
    }
    
    .ng-valid.ng-dirty {
    border-color: #78FA89;
    }
    
    .ng-pristine.ng-invalid
    {
        border-color: #333333;
    }
    


Result




By-藍小伙