Cách yêu cầu bộ điều khiển trong chỉ thị anglejs


86

Bất cứ ai có thể cho tôi biết làm thế nào để bao gồm một bộ điều khiển từ một chỉ thị trong một chỉ thị angleJS khác. ví dụ tôi có đoạn mã sau

var app = angular.module('shop', []).
config(['$routeProvider', function ($routeProvider) {
    $routeProvider.when('/', {
        templateUrl: '/js/partials/home.html'
    })
        .when('/products', {
        controller: 'ProductsController',
        templateUrl: '/js/partials/products.html'
    })
        .when('/products/:productId', {
        controller: 'ProductController',
        templateUrl: '/js/partials/product.html'
    });
}]);

app.directive('mainCtrl', function () {
    return {
        controller: function ($scope) {}
    };
});

app.directive('addProduct', function () {
    return {
        restrict: 'C',
        require: '^mainCtrl',
        link: function (scope, lElement, attrs, mainCtrl) {
            //console.log(cartController);
        }
    };
});

Bằng tất cả tài khoản, tôi sẽ có thể truy cập bộ điều khiển trong chỉ thị addProduct nhưng tôi thì không. Có cách nào tốt hơn để làm điều này không?


5
requiređảm bảo sự hiện diện của một chỉ thị khác và sau đó bao gồm bộ điều khiển của nó. ^requirekiểm tra các phần tử phía trên phần tử hiện tại ngoài phần tử hiện tại. Vì vậy, bạn phải sử dụng hai chỉ thị cùng nhau để điều này hoạt động. Nếu không, chỉ cần xác định một bộ điều khiển với app.controllervà sau đó sử dụng nó trong cả hai lệnh. Dù bằng cách nào, bạn có thể đặt nó vào một Plunker đơn giản cùng với mã HTML của mình không?
Josh David Miller

Câu trả lời:


187

Tôi đã may mắn và đã trả lời câu hỏi này trong một nhận xét cho câu hỏi, nhưng tôi đang đăng một câu trả lời đầy đủ vì mục đích đầy đủ và vì vậy chúng tôi có thể đánh dấu câu hỏi này là "Đã trả lời".


Nó phụ thuộc vào những gì bạn muốn hoàn thành bằng cách chia sẻ một bộ điều khiển; bạn có thể chia sẻ cùng một bộ điều khiển (mặc dù có các phiên bản khác nhau) hoặc bạn có thể chia sẻ cùng một phiên bản bộ điều khiển.

Chia sẻ một bộ điều khiển

Hai chỉ thị có thể sử dụng cùng một bộ điều khiển bằng cách truyền cùng một phương thức cho hai chỉ thị, như sau:

app.controller( 'MyCtrl', function ( $scope ) {
  // do stuff...
});

app.directive( 'directiveOne', function () {
  return {
    controller: 'MyCtrl'
  };
});

app.directive( 'directiveTwo', function () {
  return {
    controller: 'MyCtrl'
  };
});

Mỗi chỉ thị sẽ nhận được thể hiện riêng của bộ điều khiển, nhưng điều này cho phép bạn chia sẻ logic giữa bao nhiêu thành phần tùy thích.

Yêu cầu một bộ điều khiển

Nếu bạn muốn chia sẻ cùng một phiên bản của bộ điều khiển, thì bạn sử dụng require.

requiređảm bảo sự hiện diện của một chỉ thị khác và sau đó bao gồm bộ điều khiển của nó làm tham số cho hàm liên kết. Vì vậy, nếu bạn có hai chỉ thị trên một phần tử, chỉ thị của bạn có thể yêu cầu sự hiện diện của chỉ thị kia và có quyền truy cập vào các phương thức điều khiển của nó. Một trường hợp sử dụng phổ biến cho điều này là yêu cầu ngModel.

^require, với việc thêm dấu mũ, kiểm tra các phần tử ở trên chỉ thị ngoài phần tử hiện tại để cố gắng tìm chỉ thị khác. Điều này cho phép bạn tạo các thành phần phức tạp nơi "các thành phần con" có thể giao tiếp với thành phần mẹ thông qua bộ điều khiển của nó để tạo ra hiệu quả lớn. Ví dụ có thể bao gồm các tab, trong đó mỗi ngăn có thể giao tiếp với các tab tổng thể để xử lý chuyển đổi; một bộ đàn accordion có thể đảm bảo chỉ có một cái được mở tại một thời điểm; Vân vân.

Trong cả hai trường hợp, bạn phải sử dụng hai chỉ thị cùng nhau để điều này hoạt động. requirelà một cách giao tiếp giữa các thành phần.

Xem trang Hướng dẫn của các chỉ thị để biết thêm thông tin: http://docs.angularjs.org/guide/directive


4
Có thể yêu cầu một bộ điều khiển chỉ thị anh chị em không? Về cơ bản, tôi cần chia sẻ cùng một phiên bản của bộ điều khiển hoặc dịch vụ giữa các chỉ thị anh chị em (như trong DOM anh chị em, không phải trên cùng một phần tử DOM) được lặp lại bằng cách sử dụng ng-repeat. Hãy tưởng tượng mỗi mục được lặp lại có một chỉ thị cần một trạng thái hoặc logic được chia sẻ giữa chúng.
CMCDragonkai

2
@CMCDragonkai Không có cách nào để làm điều đó, nhưng có hai cách phổ biến để hoàn thành cùng một việc. Đầu tiên là nếu tất cả các anh chị em đều thuộc cùng một "kiểu" thì phần tử phía trên ngRepeat có thể giống như một chỉ thị vùng chứa và tất cả các phần tử con sau đó có thể yêu cầu chỉ thị đó thay thế, tất cả đều chia sẻ cùng một bộ điều khiển. Giải pháp phổ biến hơn - và thường là chuẩn hơn - là sử dụng dịch vụ chia sẻ. Bạn có thể nói rõ hơn về những gì anh chị em này làm và những gì họ cần chia sẻ?
Josh David Miller

Yep đã thực hiện tùy chọn đầu tiên. Sử dụng bộ điều khiển chỉ thị vùng chứa. Hoạt động tuyệt vời. Nó dành cho Masonry.
CMCDragonkai

Đây là một câu trả lời tuyệt vời và đã củng cố sự hiểu biết của tôi về cách tất cả những điều này hoạt động. Cảm ơn! (Xin lưu ý, đây có thể là một tính năng mới hơn, nhưng bạn có thể sử dụng requiređể chỉ định một chỉ thị hoặc một mảng chỉ thị; mỗi chỉ thị có thể được bắt đầu bằng dấu mũ ( ^) cho các yêu cầu chi tiết hơn.)
jedd.ahyoung

Việc sử dụng cùng một bộ điều khiển trong hai chỉ thị không cung cấp cho mỗi chỉ thị đó là cá thể riêng.
jsbisht 14/02/16

27

Có một câu trả lời hay về stackoverflow ở đây bởi Mark Rajcok:

Bộ điều khiển chỉ thị AngularJS yêu cầu bộ điều khiển chỉ thị mẹ?

với một liên kết đến jsFiddle rất rõ ràng này: http://jsfiddle.net/mrajcok/StXFK/

<div ng-controller="MyCtrl">
    <div screen>
        <div component>
            <div widget>
                <button ng-click="widgetIt()">Woo Hoo</button>
            </div>
        </div>
    </div>
</div>

JavaScript

var myApp = angular.module('myApp',[])

.directive('screen', function() {
    return {
        scope: true,
        controller: function() {
            this.doSomethingScreeny = function() {
                alert("screeny!");
            }
        }
    }
})

.directive('component', function() {
    return {
        scope: true,
        require: '^screen',
        controller: function($scope) {
            this.componentFunction = function() {
                $scope.screenCtrl.doSomethingScreeny();
            }
        },
        link: function(scope, element, attrs, screenCtrl) {
            scope.screenCtrl = screenCtrl
        }
    }
})

.directive('widget', function() {
    return {
        scope: true,
        require: "^component",
        link: function(scope, element, attrs, componentCtrl) {
            scope.widgetIt = function() {
                componentCtrl.componentFunction();
            };
        }
    }
})


//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});

function MyCtrl($scope) {
    $scope.name = 'Superhero';
}

4
Đối với tôi, điều khiến ví dụ của Mark Rajcok được nhấp chuột nhiều nhất là chú ý đến cách các phương thức bộ điều khiển được tạo ra. Thông thường, bạn thấy các phương thức bộ điều khiển được tạo qua $ scope.methodName = function () {...}, nhưng để điều này hoạt động, bạn phải sử dụng this.methodName cho các phương thức bạn muốn truy cập. Tôi đã không nhận thấy điều đó lúc đầu.
coblr
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.