AngularJs自定義指令詳解(6) - controller、require


在前面文章中提到一旦聲明了require,則鏈接函數具有第四個參數:controller。

可見require和controller是配合使用的。

在自定義指令中使用controller,目的往往是要封裝一些行為,給其他指令使用。下面是一個簡單的例子:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <script src="../lib/angular-1.3.16/angular.min.js"></script>
    <title></title>
    <script language="JavaScript">
        var app = angular.module('myapp',[]);

        app.directive('d1',function() {
            return {
                controller: function ($scope) {
                    this.method1 = function () {
                        return 'World';
                    };
                }
            }
        });

        app.directive('d2',function() {
            return {
                require: 'd1',
                link: function (scope, elem, attrs, d1) {
                    scope.greeting = d1.method1();
                }
            }
        });
    </script>
</head>
<body ng-app="myapp">
<div d1 d2>Hello {{greeting}}!</div>
</body>
</html>

 

輸出:

Hello World!

從這個例子可以看到,在DOM中需要聲明d1、d2,如果不聲明d1,那么d2在檢查require里的'd1'時,就會拋出異常。

AngularJs為我們提供了一些標記,使用它們可以告訴AngularJs怎么查找所require的控制器:

1,沒標記。在當前元素中查找,如果找不到就拋出錯誤。

2,?標記。在當前元素中查找,如果查找不到,不拋出錯誤,鏈接函數的第四個參數為null(如上面代碼link: function (scope, elem, attrs, d1)中的d1)

3,^標記。不僅在當前元素中查找,還查找其所有父級。如果找不到就拋出錯誤。

4,^^標記。只在當前元素的父級中查找。如果找不到就拋出錯誤。

5,?^標記。不僅在當前元素中查找,還查找其所有父級。如果查找不到,不拋出錯誤,鏈接函數的第四個參數為null

6,?^^標記。只在當前元素的父級中查找。如果查找不到,不拋出錯誤,鏈接函數的第四個參數為null

我們修改一下上面例子的代碼,試驗一下第4條:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <script src="../lib/angular-1.3.16/angular.min.js"></script>
    <title></title>
    <script language="JavaScript">
        var app = angular.module('myapp',[]);

        app.directive('d1',function() {
            return {
                controller: function ($scope) {
                    this.method1 = function () {
                        return 'World';
                    };
                }
            }
        });

        app.directive('d2',function() {
            return {
                require: '^^d1',
                link: function (scope, elem, attrs, d1) {
                    scope.greeting = d1.method1();
                }
            }
        });
    </script>
</head>
<body ng-app="myapp">
<div d1 d2>Hello {{greeting}}!</div>
</body>
</html>

在Chrome瀏覽器的控制台可以看到錯誤提示:

Error: [$compile:ctreq] http://errors.angularjs.org/1.3.16/$compile/ctreq?p0=d1&p1=d2

點擊鏈接去看看(需要翻牆):

Error: $compile:ctreq

Missing Required Controller
Controller 'd1', required by directive 'd2', can't be found!

果然找不到!因為d1放在d2所在的div中(當前元素),^^標記要求去父級找,當然沒有了。

在實際應用時,我們往往會require 'ngModel',也就是希望利用AngularJs內置指令ngModel里的方法,而不是自己重新寫:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <script src="../lib/angular-1.3.16/angular.min.js"></script>
    <title></title>
    <script language="JavaScript">
        var app = angular.module('myApp',[]);

        app.directive('myDirective',function() {
            return {
                require: 'ngModel',
                link: function (scope, elem, attrs, model) {
                    model.$parsers.unshift(function(value) {
                        if (parseFloat(value)<1) {
                            model.$setValidity('test', true);
                            return parseFloat(value).toFixed(2);
                        } else {
                            model.$setValidity('test', false);
                            return undefined;
                        }
                    });
                }
            }
        });

    </script>
</head>
<body ng-app="myApp">
<form name="form1">
     <div> 請輸入小於1的一個小數:<input name="input1" type="number" ng-model="aNumber" my-directive />
            保留小數點后2位:{{aNumber}}
     </div>
    <span ng-show="form1.input1.$error.test">這個數並不小於1!</span>
</form>
</body>
</html>

上面例子就是利用了ngModel里已有的$parser屬性和$setValidity方法。

$parsers里保存了一組function, 每當DOM里數據變化的時候, 這組function會被調用。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM