未被選擇人員 |
|
已被選擇人員 |
{{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; }
留言
張貼留言