2015-05-10 22 views
9

Tôi có một đối tượng data trong số MainCtrl. Đối tượng này được sử dụng để chuyển dữ liệu đến chỉ thị first-directivesecond-directive. Hai ràng buộc dữ liệu là cần thiết trong cả hai trường hợp.Gửi thông số cho các chỉ thị lồng nhau với phạm vi bị cô lập

Đối first-directive, tôi vượt qua các đối tượng hoàn chỉnh data nhưng đối với second-directive Tôi muốn vượt qua numbers đối tượng (scope.numbers = scope.dataFirst.numbers).

Vấn đề:

Khi tôi làm <div second-directive="dataFirst.numbers"></div>, và tôi kiểm tra xem dataSecond là một đối tượng, nó sẽ trả true.

Nhưng khi tôi làm <div second-directive="numbers"></div> và tôi kiểm tra xem dataSecond có phải là một đối tượng không, nó trả về false.

Trong cả hai trường hợp, nếu tôi làm console.log(scope) thuộc tính scope.dataSecond được hiển thị.

Câu hỏi đặt ra:

Tại sao điều này xảy ra và cách chính xác để vượt qua params để chỉ thị là gì?

EDIT: Ý tưởng đưa ra chỉ thị có thể sử dụng lại và điều này ngụ ý rằng chúng không thể phụ thuộc vào chỉ thị của người khác.

angular.module('app',[]) 
 

 
.controller('MainCtrl', function($scope) { 
 
    $scope.data = { 
 
    numbers: { 
 
     n1: 'one', 
 
     n2: 'two' 
 
    }, 
 
    letters: { 
 
     a: 'A', 
 
     b: 'B' 
 
    } 
 
    } 
 
}) 
 

 
.directive('firstDirective', function() { 
 
    return { 
 
    template: '<div class="first-directive">\ 
 
     <h2>First Directive</h2>\ 
 
     {{dataFirst}}\ 
 
     <div second-directive="dataFirst.numbers"></div>\ 
 
     <div second-directive="numbers"></div>\ 
 
     </div>', 
 
    replace: true, 
 
    restrict: 'A', 
 
    scope: { 
 
     dataFirst: '=firstDirective' 
 
    }, 
 
    link: function postLink(scope, element, attrs) { 
 
     console.log('first directive') 
 
     console.log(scope) 
 
     scope.numbers = scope.dataFirst.numbers; 
 
    } 
 
    }; 
 
}) 
 

 
.directive('secondDirective', function() { 
 
    return { 
 
    template: '<div class="second-directive">\ 
 
     <h2>Second Directive</h2>\ 
 
     {{dataSecond}}\ 
 
     <div class="is-obj">is an object: {{isObj}}</div>\ 
 
     </div>', 
 
    replace: true, 
 
    restrict: 'A', 
 
    scope: { 
 
     dataSecond: '=secondDirective' 
 
    }, 
 
    link: function postLink(scope, element, attrs) { 
 
     console.log('second directive'); 
 
     console.log(scope) 
 
     
 
     // <div second-directive="XXXX"></div> 
 
     // if 'numbers' returns undefined 
 
     // if 'dataFirst.numbers' returns the object 
 
     console.log(scope.dataSecond); 
 
     
 
     scope.isObj = false; 
 
     
 
     if(angular.isObject(scope.dataSecond)){ 
 
     scope.isObj = true; 
 
     } 
 
    } 
 
    }; 
 
});
h2 { 
 
    padding: 0; 
 
    margin: 0; 
 
} 
 

 
.first-directive { 
 
    background: #98FFDA; 
 
    color: black; 
 
    padding: 10px; 
 
} 
 

 
.second-directive { 
 
    background: #FFA763; 
 
    color: white; 
 
    padding: 10px; 
 
} 
 

 
.is-obj { 
 
    background: blue; 
 
}
<!DOCTYPE html> 
 
<html ng-app="app"> 
 

 
    <head> 
 
    <meta charset="utf-8" /> 
 
    <title>AngularJS Plunker</title> 
 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 
    </head> 
 

 
    <body ng-controller="MainCtrl"> 
 
    <h2>MainCtrl</h2> 
 
    {{data}} 
 

 
    <div first-directive="data"> 
 
    </div> 
 

 
    <div second-directive="data"> 
 
    </div> 
 
    </body> 
 

 
</html>

Trả lời

10

tôi sẽ lặp lại những gì người khác trước khi tôi nói - rằng link chức năng của firstDirective là một bài chức năng -Link chạy sau các link chức năng của secondDirective, và vì vậy scope.numbers chưa được gán đối tượng scope.dataFirst.numbers.

Tuy nhiên, giải pháp kết hợp chặt chẽ hai chỉ thị qua require dường như không tối ưu với tôi.

Thay vào đó, để đảm bảo rằng một tài sản phạm vi được phân công đúng trong các phụ huynh trước khi bên trong chỉ thị/con chạy (như secondDirective, trong trường hợp này) là sử dụng một tiền chức năng -Link trong firstDirective (thay vì một bài -Link)

link: { 
    pre: function prelink(scope){ 
     console.log('first directive') 
     console.log(scope) 
     scope.numbers = scope.dataFirst.numbers; 
    } 
} 

Demo

9

Giải pháp của tôi để này sẽ có chỉ thị thứ hai kế thừa các thuộc tính đối tượng dữ liệu từ các chỉ thị đầu tiên.

angular.module('app', []) 
 

 
.controller('MainCtrl', function($scope) { 
 
    $scope.data = { 
 
    numbers: { 
 
     n1: 'one', 
 
     n2: 'two' 
 
    }, 
 
    letters: { 
 
     a: 'A', 
 
     b: 'B' 
 
    } 
 
    } 
 
}) 
 

 
.directive('firstDirective', function() { 
 
    return { 
 
    template: '<div class="first-directive">\ 
 
     <h2>First Directive</h2>\ 
 
     {{dataFirst}}\ 
 
     <div second-directive></div>\ 
 
     <div second-directive></div>\ 
 
     </div>', 
 
    replace: true, 
 
    restrict: 'A', 
 
    scope: { 
 
     dataFirst: '=firstDirective' 
 
    }, 
 
    controller: function firstDirectiveController($scope) { 
 
     return $scope; 
 
    }, 
 
    link: function postLink(scope, element, attrs) { 
 
     console.log('first directive') 
 
     console.log(scope) 
 
     scope.numbers = scope.dataFirst.numbers; 
 
    } 
 
    }; 
 
}) 
 

 
.directive('secondDirective', function() { 
 
    return { 
 
    template: '<div class="second-directive">\ 
 
     <h2>Second Directive</h2>\ 
 
     {{dataSecond}}\ 
 
     <div class="is-obj">is an object: {{isObj}}</div>\ 
 
     </div>', 
 
    replace: true, 
 
    require: '^firstDirective', 
 
    link: function postLink(scope, iElement, iAttrs, firstDirectiveController) { 
 
     console.log('second directive'); 
 
     console.log(firstDirectiveController.dataFirst.numbers); 
 
     
 
     scope.dataSecond = firstDirectiveController.dataFirst.numbers; 
 

 
     scope.isObj = false; 
 

 
     if (angular.isObject(scope.dataSecond)) { 
 
     scope.isObj = true; 
 
     } 
 
    } 
 
    }; 
 
}); 
 
h2 { 
 
    padding: 0; 
 
    margin: 0; 
 
} 
 

 
.first-directive { 
 
    background: #98FFDA; 
 
    color: black; 
 
    padding: 10px; 
 
} 
 

 
.second-directive { 
 
    background: #FFA763; 
 
    color: white; 
 
    padding: 10px; 
 
} 
 

 
.is-obj { 
 
    background: blue; 
 
}

 
<!DOCTYPE html> 
 
<html ng-app="app"> 
 

 
    <head> 
 
    <meta charset="utf-8" /> 
 
    <title>AngularJS Plunker</title> 
 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 
     <link rel="stylesheet" href="style.css"> 
 
    <script src="script.js"></script> 
 
    </head> 
 

 
    <body ng-controller="MainCtrl"> 
 
    <h2>MainCtrl</h2> 
 
    {{data}} 
 

 
    <div first-directive="data"> 
 
    </div> 
 
    </body> 
 

 
</html>

+2

Đó là một câu trả lời tốt nếu bạn biết thứ tự lồng nhau của các chỉ thị trong html. Ý tưởng của tôi là làm cho các thành phần tái sử dụng (như dropdowns) và điều này ngụ ý rằng bạn không biết thứ tự. Ví dụ, nếu bạn cố gắng đặt 'chỉ thị thứ hai' trong' ', nó không hoạt động vì nó cần' chỉ thị đầu tiên'. Cảm ơn bạn :) – cespon

+2

Giải pháp này chắc chắn hoạt động (mặc dù, nó không nhất thiết kết hợp chặt chẽ hai chỉ thị với nhau), nhưng một câu trả lời tốt nên nhiều hơn chỉ là mã. –

Các vấn đề liên quan