| 未被選擇人員 |
|
已被選擇人員 |
| {{PerMembers|json}} | ||
Source Code:http://plnkr.co/edit/riXlgw?p=preview
一、由於Html原本並無提供Dualbox功能,故範例中利用自訂Directive製作Dualbox,並使用Factory來處理運算或一些邏輯判斷,如此更可實現關注點分離的概念。
(一)關注點分離:主要目的是將業務邏輯及View分離,如此一來開發人員可以將注意力 集中於業務邏輯的開發,將與業務邏輯無關的功能分開處理,簡化開發複雜度及方便日 後維護。
(二)Directive:所謂Directive就如html中的<div>、<table>等標籤,在AngularJS中不僅可以使用預設的Directive之外,也能自訂Directive,通常使用方式:
app.directive("test1",function(){
return {
restrict: "E",
template: "<div>test</div>"
};
});
屬性說明如下:
restrict 說明該directive要以何種方式宣告,像是元素、屬性、註解
A’ – Attribute (You want to use your directive as <div rating>)
‘E’ – Element (Use it as <rating>)
‘C’ – Class. (Use it like <div class=”rating”>)
‘M’ – Comment (Use it like <!– directive: rating –>)
priority 說明該directive和其他在同個元素的directive的優先度為何,數字越小優先度越高
template 用字串的方式編寫HTML碼,使用該directive的元素將會替換為這裡指定的HTML
templateUrl 同template,但是是指定template的url
replace 若為true則會用template取代原本的Html元素,若為false則將元素insert到元本的Html裡面
transclude 設為true可以將原本的HTML的元素內容移到template定義的HTML元素裡
scope 若給一物件則會建立一個新的scope,若指定為true則繼成自父scope
controller 為directive定義一個controller(大部分的目的是為了和其他directive互動)
require 指定該directive需要和哪些directive互動
link 可以在該方法內增加監聽事件($scope.$watch),或初始化一些資訊
compile 在link執行之前會先被執行,用於用程式動態修改template
自訂Directive的好處在於html所提供的控件有限且能做到的功能不多,但當我們可以自 訂Directive後便能創造專屬控件,並賦予特殊功能,就相當於Asp.Net中的WebControl,且都在前端進行處理,不需要每次操作都回到後端。
(三)Factory:Angularjs中重要概念Service,可以將Controller中共用的邏輯收納成一個Service,而該Service提供了三種方式,以複雜度來區分為:Service<Factory<Provider,各使用時機大致如下:
1.Service:當外部已經寫好某服務的Constructor時,可透過service直接用Constructor來註冊服務。
myApp.service('myService', function(){
});
2.Factory:自行製作服務時。myApp.factory('myFactory', function(){
return {
};
});
3.Provider:希望服務能夠客制化,在注入時做一些設定和調整。myApp.provider('myProvider', function(){
return {
};
$get: function(){
return{
};
};
});
二、首先我們設計出DefaultView並使用自訂標籤<dual-box></dual-box>
<html>
<head>
<link href="//da7xgjtj801h2.cloudfront.net/2014.2.716/styles/kendo.common.min.css" rel="stylesheet" type="text/css" />
<link href="//da7xgjtj801h2.cloudfront.net/2014.2.716/styles/kendo.default.min.css" rel="stylesheet" type="text/css" />
<link href="Option.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"></script>
<script src="//code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="//da7xgjtj801h2.cloudfront.net/2014.2.716/js/kendo.ui.core.min.js"></script>
<script src="listApp.js"></script>
<script src="listFactory.js"></script>
<script src="listDirective.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body ng-app="listAppModule">
<dual-box>
<div>{{PerMembers|json}}</div>
</dual-box>
</body>
</html>
三、再來設計dualBox.htm獨立成一個UI,並套入一些model、function來顯示資料及進行異動,於此我們只是先大致上定義model name、function可傳入的值,而實作部分則置於Factory。
<div>
<table class="ifo" cellpadding="0" cellspacing="0" border="0" height="144px;" width="300px;">
<tr>
<td>
未被選擇人員
<select class="options" id="listView" size="10" id="myselection" multiple ng-multiple="true" ng-model="NonPermissions" ng-options="id as id for (id, ifo) in NonPerMembers" ng-dblclick="move(NonPerMembers, PerMembers, NonPermissions);"></select>
</td>
<td valign="center">
<button class="btn btn-default" ng-click="move(NonPerMembers, PerMembers, NonPermissions);">></button>
<br />
<button class="btn btn-default" ng-click="move(PerMembers, NonPerMembers, Permissions);"><</button>
</td>
<td>
已被選擇人員
<select class="options" size="10" multiple="" ng-model="Permissions" ng-options="id as id for (id, ifo) in PerMembers" ng-dblclick="move(PerMembers, NonPerMembers, Permissions);"></select>
</td>
</tr>
<tr><td colspan="3" align="right"><button class="btn btn-info">確定</button><button class="btn btn-info" data-dismiss="modal">取消</button></td></tr>
</table>
</div>
<div ng-transclude></div><!--可讓外部擴充控件等-->
四、撰寫listApp.js,定義出Angularjs的module並將有引用到的directive引入。
var listboxConstractor = function(){
var listApp = angular.module('listAppModule',['listFactoryModule','listDirectiveModule',"kendo.directives"]);
}();
五、建構出listFactory.js定義出要實作之功能,如載入初始資料、兩個listbox間的移動。
var listFactoryConstruct = function(){
var app = angular.module('listFactoryModule',[])
.factory('listFactoryService',function($http,$q){
return{
getData: function(jsonUrl){
var deferred = $q.defer();
var data = {
'J': {
name: 'Jack',
age: 20
}
, 'A': {
name: 'Abe',
age: 19
}
, 'B': {
name: 'Ben',
age: 18
}
, 'C': {
name: 'Cilly',
age: 22
}
, 'Z': {
name: 'Zeny',
age: 29
}
};
deferred.resolve(data);
return deferred.promise;
},
move: function(src,desc,selectedItems){
if (src.length <= 0) return;
selectedItems.forEach(
function(value){
desc[value]={"name":src[value].name,"age":src[value].age};
delete src[value];
});
}
}
});
}();
六、設計listDirective.js,設計自訂標籤,並使用dualBox.html為樣板,而Controller則扮演著業務邏輯與view的溝通。
var listDirectiveConstruct = function() {
var app = angular.module('listDirectiveModule',['listFactoryModule']);
app.directive('dualBox', function (listFactoryService)
{
return{
restrict: 'E',
templateUrl: "dualBox.html",
transclude: true,
controller: function ($scope) {
$scope.NonPerMembers = {};
$scope.PerMembers={};
listFactoryService.getData('json/listArray.json').then(
function(data){//success
$scope.NonPerMembers = data;
}
);
$scope.move = function(src,desc,selectedItems){
listFactoryService.move(src,desc,selectedItems);
}
}
}
})
}();
七、最後則處理頁面的美化部分可自訂CSS或引用套件。
.ifo{
border: 1px solid;
background-repeat: no-repeat;
background-position: 10px center;
-moz-border-radius:.5em;
-webkit-border-radius:.5em;
border-radius:.5em;
color: #202020;
margin-top: 10px;
margin-right: 0px;
margin-bottom: 10px;
margin-left: 25%;
text-align: center;
padding: 0%;
}
.options {
width: 200px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 5px;
margin-top: 10px;
margin-right: 10px;
margin-bottom: 10px;
margin-left: 10px;
}
.k-autocomplete
{
width: 92%;
vertical-align: middle;
margin-top: 10px;
margin-right: 10px;
margin-bottom: 10px;
}
.btn-info{
margin-top: 5px;
margin-right: 5px;
margin-bottom: 5px;
margin-left: 5px;
}
留言
張貼留言