วันพฤหัสบดีที่ 26 มีนาคม พ.ศ. 2558

AngularJs with Form Validation


บทความนี้อธิบายการตรวจสอบฟอร์มก่อนบันทึกข้อมูลลงใน Array เพื่อให้ข้อมูลที่จัดเก็บมีความถูกต้อง

Error Property ที่ควรรู้จัก

  • $dirty ใช้เมื่อมีการกระทำการ โดยพิมพ์บางอย่างลงไปในฟอร์มแล้ว
  • $pristine ใช้เมื่อยังไม่กระทำการใดๆ กับฟอร์ม
  • $valid ใช้ตรวจสอบข้อมูลที่กรอกลงไปในฟอร์ม ถ้าถูกต้องมีค่าเป็น true 
  • $invalid ใช้ตรวจสอบข้อมูลที่กรอกลงไปในฟอร์ม ถ้าไม่ถูกต้องมีค่าเป็น true
  • $error ใช้อ้างอิงการตรวจสอบความถูกต้องประเภทของ input เช่น url, email

ไฟล์ app.js

(function(){
app = angular.module('myapp',[]);
        app.controller('FormValidation',function(){
this.myArr=[];
this.val={};
this.countrys=['England','U.S.A','Thailand','France','Canada'];

this.addUser = function(){
this.myArr.push(this.val);
this.val={};
};
});

})();


อธิบาย : ดูคำอธิบายจาก AngularJs with ng-submit


ไฟล์ bookstore.html

<html ng-app="myapp">

<head>

<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script>
 <script type="text/javascript" src="app.js"></script>
 <style>
   span{
color:red;
   }
</style>
</head>

<body>
  <div class="row">
    <div class="col-md-12"  ng-controller="FormValidation as validCtrl">

    <form name="signUp" ng-submit="signUp.$valid && validCtrl.addUser()" novalidate>

    Country : 
    <select name="country" ng-model="validCtrl.val.country" required>
      <option ng-repeat="country in validCtrl.countrys" value="{{country}}">             {{country}}
      </option>
    </select>
    <span ng-show="signUp.country.$error.required">
    Country is required.
    </span><br><br>

    Firstname : 
    <input type ="text" name="firstname" ng-model="validCtrl.val.firstname" required />
    <span ng-show="signUp.firstname.$dirty && signUp.firstname.$error.required">Firstname is required.</span><br><br>
   
    Lastname : 
    <input type ="text" name="lastname" ng-model="validCtrl.val.lastname" required />
    <span ng-show="signUp.lastname.$pristine && signUp.lastname.$error.required">Lastname is required.</span><br><br>

    E-mail : 
    <input  type="email" name="mail" ng-model="validCtrl.val.mail" required />
    <span ng-show="signUp.mail.$invalid">
      <span ng-show="signUp.mail.$error.required">Email is required.</span>
      <span ng-show="signUp.mail.$error.email">Email is Invalid.</span>
    </span><br><br>
    URL Website : 
    <input type ="url" name="myurl" ng-model="validCtrl.val.url"  required />
    <span ng-show="signUp.myurl.$invalid">
      <span ng-show="signUp.myurl.$error.required">url is required.</span>
      <span ng-show="signUp.myurl.$error.url">url is Invalid.</span>
    </span><br><br>
 
    <div> This form is {{signUp.$valid}} </div><br>
    <input type="submit" value="Submit" />
    </form>
    <p ng-repeat="result in validCtrl.myArr">
      <b>Your Profile</b><br>
      Country : {{result.country}}<br>
      Your name : {{result.firstname}} {{result.lastname}}<br>
      Email : {{result.mail}}<br>
      URL Website : {{result.url}}
    </p>
    </div>
  </div>
 
</body>
</html>

ไม่ควรกำหนด CSS style ให้กับ tag spand โดยตรง ควรสร้าง CSS class จะเหมาะสมกว่า
 
อธิบาย :
  • Directive ที่ไม่ได้อธิบายในที่นี้ให้ดูจากบทความ AngularJs with ng-submit หรือบทความเบื้องต้นอื่นๆ
  • ng-submit จะทำงานเมื่อ ฟอร์มถูกต้อง และ สามารถเรียกใช้ฟังก์ชั่น addUser() ใน controller ได้
  • novalidate เป็นการปิดการ validate ข้อมูลที่เป็น default ของ HTML 5
  • required เป็นการกำหนดให้ระบุข้อมูลลงใน tag นั้นๆ
  • <span ng-show="signUp.country.$error.required"> ของ Dropdown List ชื่อประเทศ จะแสดง Error เมื่อไม่มีการเลือกข้อมูลจาก dropdown
  • <span ng-show="signUp.firstname.$dirty && signUp.firstname.$error.required"> ของ Firstname จะไม่แสดง Error ทันที แต่จะแสดงเมื่อมีการพิมพ์ข้อมูลลงไปใน textbox แล้ว และมีการลบข้อความที่พิมพ์ทั้งหมดทิ้ง เพราะ $dirty จะเป็น true หลังมีการกระทำบางอย่างกับฟอร์ม และเมื่อลบข้อความทั้งหมดทิ้ง ทำให้ $error.required เป็น true เช่นกัน
  • <span ng-show="signUp.lastname.$pristine && signUp.lastname.$error.required"> ของ Lastname จะแสดง Error ทันที ก่อนจะพิมพ์ข้อมูลลงไปใน textbox เพราะ $pristine จะทำงานก่อนที่จะทำการบางอย่างกับ tag
  • <span ng-show="signUp.mail.$invalid"> ของ Email จะแสดง <span ...> เมื่อข้อมูลที่กรอกไม่ถูกต้อง นั่นคือผิด format ของ email เช่น ไม่ใส่เครื่องหมาย "@"
  •  <span ng-show="signUp.mail.$error.required"> ถูกเรียกใช้งานเมื่อ signUp.mail.$invalid เป็น true และไม่มีการกรอกข้อมูลลงไปใน textbox
  • <span ng-show="signUp.mail.$error.email"> ถูกเรียกใช้งานเมื่อ signUp.mail.$invalid เป็น true และข้อมูลที่กรอกผิด format โดยมีการระบุ ว่าเป็น format email ไว้ที่ "..... $error.email"
  • ส่วนของ URL Website ก็ทำการ validate เช่นเดียวกับ Email แต่ต่างกันที่ format เป็น "..... $error.url" แทน
  • signUp.$valid จะแสดงค่าเป็น true เมื่อฟอร์มกรอกข้อมูลถูกต้องทั้งหมด และจะแสดงค่าเป็น false เมื่อกรอกข้อมูลไม่ถูกต้อง

ผลลัพธ์


ก่อนกรอกข้อมูล


หลังกรอกข้อมูลถูกต้อง






วันพุธที่ 25 มีนาคม พ.ศ. 2558

AngularJs with ng-submit


บทความนี้อธิบายการนำข้อมูลจาก form ไปเก็บไว้ใน Array หลังกดปุ่ม submit โดยเรียกใช้ Directive ng-submit และการนำข้อมูลที่ถูก push ลงไปใน Array มาแสดงผล

ไฟล์ app.js


(function(){

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

 app.controller('Registration',function(){
  this.country=['England','U.S.A','Thailand','France','Canada'];
  this.sexs=['male','female'];
  this.myArr=[];
  this.val={};

  this.addMember=function(){
   this.myArr.push(this.val);
   this.val={};
  };
 });
})();


อธิบาย :

  • สร้าง module ชื่อ myapp
  • สร้าง controller ชื่อ Registration โดยประกอบ
    • ตัวแปร country มี type เป็น Array เก็บชื่อประเทศ เพื่อนำไปแสดงใน dropdown list
    • ตัวแปร sex มี type เป็น Array เก็บเพศ เพื่อนำไปแสดงใน radio button
    • ตัวแปร myArr มี type เป็น Array ประกาศให้เป็นค่าว่าง ใช้สำหรับเก็บ object ที่รับจาก form
    • ตัวแปร val มี type เป็น Object ใช้เก็บข้อมูลแต่ละ input ผ่าน form
    • ฟังก์ชั่น addMember ทำหน้าที่เพิ่มข้อมูลไปเก็บไว้ myArr จากนั้นทำการเคลียร์ค่า Object val


ไฟล์ bookstore.html

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

<head>

<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>

<body>

<div class="container-fluid" ng-controller="Registration as regist"> 
  <div class="row">
    <div class="col-md-12">
      <form name="member" ng-submit="regist.addMember()">
      Firstname <input type="text" ng-model="regist.val.firstname" /><br><br>
      Lastname <input type="text" ng-model="regist.val.lastname" /><br><br>
      Country
      <select ng-model="regist.val.country">
        <option ng-repeat="mycountry in regist.country"  
                    value="{{mycountry}}">{{mycountry}}</option>
      </select>
      <p>Sex</p>
      <p ng-repeat="mysex in regist.sexs">
      <input type="radio" name="sex" ng-model="regist.val.sex" 
                 value="{{mysex}}" />{{mysex}}
      </p>
      <input type="submit" value="submit">
      </form>
    </div>
  </div>

  <div class="row">
    <div class="col-md-12">
      <p ng-repeat="myname in regist.myArr">
         Firstname :{{myname.firstname}} <br>
         Lastname : {{ myname.lastname }} <br>
         Sex : {{myname.sex}}<br>
         Country : {{myname.country}}
      </p>  
    </div>
  </div>

</div> 

</body>
</html>

อธิบาย :
  • เรียกใช้ module ด้วย ng-app="myapp"
  • เรียกใช้ controller ด้วย ng-controller="Registration as regist" โดยกำหนด Alias เป็น regist
  • Directive ng-submit ใน <form..> จะเรียกใช้ฟังก์ชั่น addMember() เมื่อกดปุ่ม submit 
  • ข้อมูลของการ submit 1 ครั้ง ng-model ของแต่ละ <input> จะทำการเก็บค่าเข้าไปใน Attribute แต่ละตัว ของตัวแปร val ที่มีการอ้างอิงใน ng-model โดยข้อมูลถูกเก็บในลักษณะ key:value เมื่อนำหลายๆ Attribute มารวมกันจึงเป็น 1 Object จากนั้นนำ Object ไปเก็บไว้ในตัวแปรประเภท Array เพื่อเรียกใช้งานครั้งต่อไป
  • Directive ng-model ใน input tag ต่างๆ ใช้เก็บค่าที่ได้จากการป้อนข้อมูลลงไปใน Attribute ที่อ้างอิง
  • Dropdown list และ Radio button เรียก Directive ng-repeat เพื่อวนลูปดึงข้อมูลที่เก็บใน Country[] และ Sex[] มาแสดง
  • <p ng-repeat="myname in regist.myArr"> เป็นการวนลูปดึงสมาชิกที่อยู่ใน myArr ซึ่งก็คือ Object แต่ละตัวออกมา โดยการแสดงผล ให้ระบุ Attribute ด้วย เช่น .firstname, .lastname เป็นต้น การเก็บฟอร์มไว้ใน Array จะทำให้ทุกๆ ฟอร์มที่กรอกถูกเก็บไว้ และสามารถนำมาแสดงผล หรือใช้งานอย่างอื่นได้

ผลลัพธ์

ก่อน submit Form 



หลัง submit Form








วันอาทิตย์ที่ 22 มีนาคม พ.ศ. 2558

AngularJS with ng-class

บทความนี้จะอธิบายการนำ directive ที่ชื่อ ng-class มาใช้ประโยชน์ โดย ng-class นั้น เปรียบเสมือนการเรียกใช้ property class ใน HTML tag แต่การเรียกใช้ผ่าน ng-class จะสามารถกำหนดเงื่อนไข หรือฟังก์ชั่น เพื่อเรียกใช้ class ได้

ไฟล์ bookstore.html

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

<head>

<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script>

<style>
.myclass {
background-color:blue;
color:white;
}
</style>

</head>

<body>

<div class="container-fluid" ng-init="count=0">
  <div class="row">
    <div class="col-md-12">
     <p>limited to 3 items</p>
     <input type="text" ng-class="{myclass: count===3}" ng-model="count">
     <button ng-click="count=count+1" ng-disabled="count===3">+</button>
     <button ng-click="count=count-1" ng-disabled="count===0">-</button>
    </div>
  </div>  
</div>


</body>
</html>

อธิบาย :
  • code ด้านบนไม่มีการเรียกใช้ module ใดๆ จึงไม่ได้ประกาศชื่อ module ใน ng-app
  • สร้าง CSS class กำหนดชื่อ class เป็น myclass มีพื้นหลังสีน้ำเงิน ตัวอักษรสีขาว
  • กำหนดค่าเริ่มต้นให้ count=0 ด้วย ng-init
  • กำหนดให้ myclass ถูกเรียกใช้งาน เมื่อ count เท่ากับ 3 นั่นคือ style ของ tag input จะเปลี่ยนไปเมื่อ count เป็น 3
  • เพิ่มค่าตัวแปร count เมื่อกดปุ่ม +
  • ลดค่าตัวแปร count เมื่อกดปุ่ม -
  • กำหนดให้ button ทั้งสองถูก disabled เมื่อ count มีค่าเท่ากับ 3 และ 0 เพื่อไม่ให้กดเพิ่ม item ได้มากกว่า 3 และป้องกันไม่ให้ item ติดลบ


จากตัวอย่างด้านบน จะสังเกตุว่าเป็นการเขียนเงื่อนไขไว้ภายใน tag html ซึ่งไม่สะดวกต่อการอ่าน และแก้ไขโค้ด ดังนั้น จึงควรสร้าง module และควบคุมการทำงานต่างๆ ด้วย controller ดังนี้


ไฟล์ app.js

(function(){
app = angular.module('myapp',[]);

app.controller('ButtonClick',function(){
this.count=0;

this.plus=function(){
this.count=this.count+1;
};

this.minus=function(){
this.count=this.count-1;
};

this.checkPlus=function(){
return this.count===3;
};
this.checkMinus=function(){
return this.count===0;
};
});


})();

อธิบาย :

  • สร้าง module ชื่อ myapp
  • สร้าง controller ชื่อ ButtonClick
  • ประกาศค่าเริ่มต้นให้ count ด้วย this.count=0;
  • สร้างฟังก์ชั่น plus เพื่อทำการเพิ่มค่า count
  • สร้างฟังก์ชั่น minus เพื่อทำการลดค่า count
  • สร้างฟังก์ชั่น checkPlus เพื่อตรวจสอบว่า count เท่ากับ 3 หรือไม่ ถ้าใช่ให้ return true
  • สร้างฟังก์ชั่น checkMinus เพื่อตรวจสอบว่า count เท่ากับ 0 หรือไม่ ถ้าใช่ให้ return true


ไฟล์ bootstore.html

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

<head>

<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script>
 <script type="text/javascript" src="app.js"></script>

 <style>
.myclass {
background-color:blue;
color:white;
}
</style>

</head>

<body>

<div class="container-fluid" ng-controller="ButtonClick as btn">   <div class="row">
  <div class="col-md-12">
    <p>limited to 3 items</p>
    
    <input type="text" ng-model="btn.count" ng-class="{myclass: btn.checkPlus()}">
   
    <button ng-click="btn.plus()" ng-disabled="btn.checkPlus()">+</button>

   <button ng-click="btn.minus()" ng-disabled="btn.checkMinus()">-</button> 
  </div>
 </div>  
</div>


</body>

</html>

อธิบาย :

  • เรียกใช้ module ที่ชื่อ myapp
  • include ไฟล์ app.js
  • ประกาศ Directive Controller ตั้ง alias เป็น btn
  • ประกาศ Directive ng-model เพื่อผูกค่า count ไว้กับ tag input
  • ประกาศ Directive ng-class เพื่อเรียกใช้งาน class ตามฟังก์ชั่น checkPlus
  • ประกาศ Directive ng-click ให้เรียกใช้ฟังก์ชั่น plus และ minus เมื่อคลิกปุ่ม + และ - จำทำการเพิ่มค่า/ลดค่า count
  • ประกาศ Directive ng-disabled เพื่อทำงานกับฟังก์ชั่น checkPlus และ checkMinus ซึ่งปุ่มจะถูก disabled เมื่อ ฟังก์ชั่นทั้งสอง return ค่าเป็น true


ผลลัพธ์จากการเขียนโค้ดทั้งสองรูปแบบเหมือนกัน แต่ต่างกันที่รูปแบบการเขียนโปรแกรมเท่านั้น

ผลลัพธ์



วันเสาร์ที่ 21 มีนาคม พ.ศ. 2558

AngularJS with Images

บทความนี้อธิบายการนำรูปภาพมาแสดงผลด้วย Directive ที่เรียกว่า ng-src ซึ่งจะนำมาใช้แทนการอ้างอิง resource แบบเดิมใน <img src="...">

app.js

เป็นไฟล์ที่เก็บ Module ของ application

(function(){
app = angular.module('myapp',[]);
app.controller('ImageView',function(){
this.image='Image1.jpg';
});

})();

อธิบาย :

  • ประกาศ Module ชื่อ myapp เพื่อนำไปใช้อ้างอิงใน ng-app
  • สร้าง Controller ชื่อ ImageView โดยมีตัวแปร image เก็บ Path ของไฟล์รูป เพื่อใช้อ้างอิงในการแสดงผล
image.html

เป็นไฟล์ที่ใช้แสดงผลบน Browser


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

<head>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script>
 <script type="text/javascript" src="app.js"></script>
</head>

<body>

<div class="container-fluid">
<div class="row" ng-controller="ImageView as Image">
<div class="col-md-12">
<img ng-src="{{Image.image}}" />
</div>
</div>  
</div>

</body>
</html>

อธิบาย :
  • อ้างอิง module ที่ชื่อ myapp จาก ng-app
  • include ไฟล์ app.js
  • เรียกใช้ Controller ที่ชื่อ ImageView โดยทำการตั้ง Alias name เพื่อสะดวกในการเขียนโปรแกรม
  • Directive ng-src ทำการแสดง Path รูปภาพ จากตัวแปร image

จากนั้นทำการปรับแต่งรูปแบบการแสดงผล ให้แสดงหลายๆภาพได้ โดยเพิ่ม Controller ที่ชื่อ ImageViewRepeat ใน app.js ดังนี้

app.js

(function(){
app = angular.module('myapp',[]);
app.controller('ImageView',function(){
this.image='Image1.jpg';
});
app.controller('ImageViewRepeat',function(){
this.imageArr=['Image1.jpg' , 'Image2.jpg'];
});

})(); 

อธิบาย :
  • สร้าง controller ชื่อ ImageViewRepeat 
  • สร้างตัวแปร imageArr เป็นตัวแปรประเภท Array เก็บ Path ไฟล์จำนวน 2 ภาพ
image.html

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

<head>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script>
 <script type="text/javascript" src="app.js"></script>
</head>

<body>

<div class="row" ng-controller="ImageViewRepeat as ImageRep">
<div class="col-md-12" ng-repeat="image in ImageRep.imageArr">
<img ng-src="{{image}}" width='50px' height='50px' />
</div>
</div>

</body>
</html>

อธิบาย :
  • แก้ไข .row โดยเปลี่ยนชื่อ Directive Controller เป็น ImageViewRepeat as ImageRep
  • ใช้ Directive ng-repeat เพื่อวนลูปดึง Path รูปภาพใน array มาแสดงผล
ผลลัพธ์ที่ได้