在前几篇随笔简单介绍了AngularJS,在AngularJS 指令(directive)是重要的概念,主要负责了很大部分的组建样式交互。在前面介绍过directive需要预先的模板编译在返回一个link的函数,注册行为事件交互等等。在这里不多说了,关于指令的介绍将在后续一并补上。在这里我们先看一个利用jQuery UI组件开发的AngularJS Autocomplete指令。
代码:jsfiddle在线测试
Directive:
1
var oldSuggest = jQuery.ui.autocomplete.prototype._suggest;
2 jQuery.ui.autocomplete.prototype._suggest =
function(items) {
3
var itemsArray = items;
4
if (
this.options.maxItems &&
this.options.maxItems > 0) {
5 itemsArray = items.slice(0,
this.options.maxItems);
6 }
7 oldSuggest.call(
this, itemsArray);
8 };
9
10
var autocomplete =
function() {
11
var linkFun =
function($scope, element, attrs) {
12
var $input = jQuery(element);
13
var responseDataSource =
function($scope, source, pattern, response) {
14
var express = $scope[source];
15
var data =
typeof(express) === "function" ? express(pattern, response) : express;
16
if (data) {
17 response(data);
18 }
19 };
20
var option = attrs;
21
//
22 option.position = {
23 my: attrs.positionMy,
24 at: attrs.positionAt,
25 };
26
var option = jQuery.extend({
27 position: {
28 my: "",
29 at: ""
30 },
31 close:
function(event, ui) {
32
var express = attrs["ngModel"] + "='" + $input.val() + "'";
33 $scope.$apply(express);
34 $scope.$eval(attrs["ngChange"]);
35 }
36 }, option);
37 option.remote = option.remote === "true";
38
if (!option.remote) {
39 option.dataSource = attrs.source;
40 option.source =
function(pattern, response) {
41
var option = $input.autocomplete("option");
42
var responseEx =
function(data) {
43
var matches = jQuery.map(data,
function(tag) {
44
var startWith = attrs.startWith === "true";
45
var index = tag.toUpperCase().indexOf(pattern.term.toUpperCase())
46
if ((startWith && index === 0) || (!startWith && index > -1)) {
47
return tag;
48 }
49 })
50 response(matches);
51 };
52 responseDataSource($scope, option.dataSource, pattern, responseEx);
53 };
54 }
else {
55 option.source = option.source;
//
remote url
56 }
57 $input.autocomplete(option);
58 };
59
return linkFun;
60 };
61
62
var prefixed = "green";
63
var appMoule = angular.module('app', []);
64
65 appMoule.directive(prefixed + "Autocomplete", autocomplete);
在指令中主需要标注html attribute green-autocomplete=””引用.
以及一些特殊option:
- Remote:(Boolean)是否为远程调用,true则source为url,false则为scope上的一个属性或者函数。
- Source:数据源,url、scope属性或者函数。
- min-length:开始显示下拉条的最小长度。
- position-my,position-at:jQuery下拉条显示样式
- start-with:(Boolean)是否为以前缀开始的帅选,默认false(包含)。
- max-items:显示最大下拉项数目。
测试代码:
html: 1 <div ng-app="app" ng-controller="Test">
2
<
div
class
="ui-widget"
>
3
<
label
for
="tags"
>Tags(变量):
</
label
>
4
<
input
id
="tags"
ng-model
="val"
green-autocomplete
=""
remote
="false"
ng-disabled
="val=='Asp'"
source
="getsource"
min-length
="0"
position-my
="right top"
position-at
= "right bottom"
start-with
="false"
>
5
</
div
>
6
<
br
/>
7 {{val}}
8
9
<
div
class
="ui-widget"
>
10
<
label
for
="tags"
>Tags(函数):
</
label
>
11
<
input
i ng-model
="val_Array"
green-autocomplete
=""
source
="availableTags"
max-items
="5"
min-length
="2"
start-with
="true"
ng-change
="change();"
>
12
</
div
>
13
<
br
/>{{val_Array}}
14 http://XX/XX.php?term={0}
15
<
div
class
="ui-widget"
>
16
<
label
for
="tags"
>Tags(url):
</
label
>
17
<
input
i ng-model
="val_url"
green-autocomplete
=""
source
="url"
remote
="true"
max-items
="3"
>
18
</
div
>
19
<
br
/>
20 {{val_url}}
21
</
div
>
javascript:
1
//
test controller
2
var test =
function($scope) {
3 $scope.availableTags = [
4 "ActionScript",
5 "AppleScript",
6 "Asp",
7 "BASIC",
8 "C",
9 "C++",
10 "Clojure",
11 "COBOL",
12 "ColdFusion",
13 "Erlang",
14 "Fortran",
15 "Groovy",
16 "Haskell",
17 "Java",
18 "JavaScript",
19 "Lisp",
20 "Perl",
21 "PHP",
22 "Python",
23 "Ruby",
24 "Scala",
25 "Scheme"
26 ];
27
28 $scope.getsource =
function(pattern, response) {
29 response($scope.availableTags);
30 };
31 $scope.change =
function() {
32 console.log('change', $scope.val_Array);
33 };
34 };
35
36 appMoule.controller("Test", test);
37
//
mock ajax.
38
var oldAjax = jQuery.ajax;
39 jQuery.ajax =
function(param) {
40
if (param.url === "url") {
41
var term = param.data.term;
42 param.success([term + "1", term + "2", 3 + term, 4 + term]);
43 }
44
else {
45 oldAjax(param);
46 }
47 };
48
49 //jQuery.ajax({url:"text.html"}); must erroe:GET http://fiddle.jshell.net/_display/text.html 404 (NOT FOUND)
在测试中为了验证url,本想通过自己的博客导入json数据,但是跨域等问题,所以没办法,在最后选择了mock jQuery.Ajax,本想引入jasmine测试框架利用spyOn(jasmine测试mock文档:
http://pivotal.github.com/jasmine/jsdoc/symbols/jasmine.Spy.html),但是找了很久没找到在线引用包。最后采用手动血mock代码如下:
1
//
mock ajax.
2
var oldAjax = jQuery.ajax;
3 jQuery.ajax =
function(param) {
4
if (param.url === "url") {
5
var term = param.data.term;
6 param.success([term + "1", term + "2", 3 + term, 4 + term]);
7 }
8
else {
9 oldAjax(param);
10 }
11 };
所以你看见的第三个返回值永远会是输入前缀加1,2,3.
测试第一输入框测试scope属性,第二测试scope函数(有两个输入参数),第三测试url ajax。