Cách dễ nhất để chuyển một biến phạm vi AngularJS từ chỉ thị đến bộ điều khiển là gì? Tất cả các ví dụ mà tôi đã thấy có vẻ rất phức tạp, không có cách nào để tôi có thể truy cập bộ điều khiển từ một chỉ thị và đặt một trong các biến phạm vi của nó?
Cách dễ nhất để chuyển một biến phạm vi AngularJS từ chỉ thị đến bộ điều khiển là gì? Tất cả các ví dụ mà tôi đã thấy có vẻ rất phức tạp, không có cách nào để tôi có thể truy cập bộ điều khiển từ một chỉ thị và đặt một trong các biến phạm vi của nó?
Câu trả lời:
Đã chỉnh sửa vào ngày 25 tháng 8 năm 2014: Đây là nơi tôi đã chia nó.
Cảm ơn @anvarik.
Đây là JSFiddle . Tôi quên nơi tôi đã đặt cái này. Nhưng đây là một ví dụ điển hình cho bạn thấy sự khác biệt giữa = và @
<div ng-controller="MyCtrl">
<h2>Parent Scope</h2>
<input ng-model="foo"> <i>// Update to see how parent scope interacts with component scope</i>
<br><br>
<!-- attribute-foo binds to a DOM attribute which is always
a string. That is why we are wrapping it in curly braces so
that it can be interpolated. -->
<my-component attribute-foo="{{foo}}" binding-foo="foo"
isolated-expression-foo="updateFoo(newFoo)" >
<h2>Attribute</h2>
<div>
<strong>get:</strong> {{isolatedAttributeFoo}}
</div>
<div>
<strong>set:</strong> <input ng-model="isolatedAttributeFoo">
<i>// This does not update the parent scope.</i>
</div>
<h2>Binding</h2>
<div>
<strong>get:</strong> {{isolatedBindingFoo}}
</div>
<div>
<strong>set:</strong> <input ng-model="isolatedBindingFoo">
<i>// This does update the parent scope.</i>
</div>
<h2>Expression</h2>
<div>
<input ng-model="isolatedFoo">
<button class="btn" ng-click="isolatedExpressionFoo({newFoo:isolatedFoo})">Submit</button>
<i>// And this calls a function on the parent scope.</i>
</div>
</my-component>
</div>
var myModule = angular.module('myModule', [])
.directive('myComponent', function () {
return {
restrict:'E',
scope:{
/* NOTE: Normally I would set my attributes and bindings
to be the same name but I wanted to delineate between
parent and isolated scope. */
isolatedAttributeFoo:'@attributeFoo',
isolatedBindingFoo:'=bindingFoo',
isolatedExpressionFoo:'&'
}
};
})
.controller('MyCtrl', ['$scope', function ($scope) {
$scope.foo = 'Hello!';
$scope.updateFoo = function (newFoo) {
$scope.foo = newFoo;
}
}]);
Tôi đã phải loay hoay với điều này và không thể làm cho nó hoạt động ngay cả với biến được xác định "="
trong phạm vi. Đây là ba giải pháp tùy thuộc vào tình huống của bạn.
Tôi nhận thấy rằng biến chưa được đánh giá bằng góc khi nó được chuyển tới chỉ thị. Điều này có nghĩa là bạn có thể truy cập nó và sử dụng nó trong mẫu, nhưng không phải bên trong liên kết hoặc chức năng bộ điều khiển ứng dụng trừ khi chúng tôi đợi nó được đánh giá.
Nếu biến của bạn đang thay đổi hoặc được tìm nạp thông qua một yêu cầu, bạn nên sử dụng $observe
hoặc $watch
:
app.directive('yourDirective', function () {
return {
restrict: 'A',
// NB: no isolated scope!!
link: function (scope, element, attrs) {
// observe changes in attribute - could also be scope.$watch
attrs.$observe('yourDirective', function (value) {
if (value) {
console.log(value);
// pass value to app controller
scope.variable = value;
}
});
},
// the variable is available in directive controller,
// and can be fetched as done in link function
controller: ['$scope', '$element', '$attrs',
function ($scope, $element, $attrs) {
// observe changes in attribute - could also be scope.$watch
$attrs.$observe('yourDirective', function (value) {
if (value) {
console.log(value);
// pass value to app controller
$scope.variable = value;
}
});
}
]
};
})
.controller('MyCtrl', ['$scope', function ($scope) {
// variable passed to app controller
$scope.$watch('variable', function (value) {
if (value) {
console.log(value);
}
});
}]);
Và đây là html (hãy nhớ dấu ngoặc!):
<div ng-controller="MyCtrl">
<div your-directive="{{ someObject.someVariable }}"></div>
<!-- use ng-bind in stead of {{ }}, when you can to avoids FOUC -->
<div ng-bind="variable"></div>
</div>
Lưu ý rằng bạn không nên đặt biến "="
trong phạm vi, nếu bạn đang sử dụng $observe
hàm. Ngoài ra, tôi thấy rằng nó truyền các đối tượng dưới dạng chuỗi, vì vậy nếu bạn đang chuyển các đối tượng, hãy sử dụng giải pháp # 2 hoặc scope.$watch(attrs.yourDirective, fn)
(hoặc # 3 nếu biến của bạn không thay đổi).
Nếu biến của bạn được tạo trong một bộ điều khiển khác , chẳng hạn như một bộ điều khiển khác , nhưng chỉ cần đợi cho đến khi góc đánh giá nó trước khi gửi nó đến bộ điều khiển ứng dụng, chúng ta có thể sử dụng $timeout
để đợi cho đến khi $apply
nó chạy. Ngoài ra, chúng tôi cần sử dụng $emit
để gửi nó đến bộ điều khiển ứng dụng phạm vi mẹ (do phạm vi bị cô lập trong chỉ thị):
app.directive('yourDirective', ['$timeout', function ($timeout) {
return {
restrict: 'A',
// NB: isolated scope!!
scope: {
yourDirective: '='
},
link: function (scope, element, attrs) {
// wait until after $apply
$timeout(function(){
console.log(scope.yourDirective);
// use scope.$emit to pass it to controller
scope.$emit('notification', scope.yourDirective);
});
},
// the variable is available in directive controller,
// and can be fetched as done in link function
controller: [ '$scope', function ($scope) {
// wait until after $apply
$timeout(function(){
console.log($scope.yourDirective);
// use $scope.$emit to pass it to controller
$scope.$emit('notification', scope.yourDirective);
});
}]
};
}])
.controller('MyCtrl', ['$scope', function ($scope) {
// variable passed to app controller
$scope.$on('notification', function (evt, value) {
console.log(value);
$scope.variable = value;
});
}]);
Và đây là html (không có dấu ngoặc!):
<div ng-controller="MyCtrl">
<div your-directive="someObject.someVariable"></div>
<!-- use ng-bind in stead of {{ }}, when you can to avoids FOUC -->
<div ng-bind="variable"></div>
</div>
Nếu biến của bạn không thay đổi và bạn cần đánh giá nó trong chỉ thị của mình, bạn có thể sử dụng $eval
hàm:
app.directive('yourDirective', function () {
return {
restrict: 'A',
// NB: no isolated scope!!
link: function (scope, element, attrs) {
// executes the expression on the current scope returning the result
// and adds it to the scope
scope.variable = scope.$eval(attrs.yourDirective);
console.log(scope.variable);
},
// the variable is available in directive controller,
// and can be fetched as done in link function
controller: ['$scope', '$element', '$attrs',
function ($scope, $element, $attrs) {
// executes the expression on the current scope returning the result
// and adds it to the scope
scope.variable = scope.$eval($attrs.yourDirective);
console.log($scope.variable);
}
]
};
})
.controller('MyCtrl', ['$scope', function ($scope) {
// variable passed to app controller
$scope.$watch('variable', function (value) {
if (value) {
console.log(value);
}
});
}]);
Và đây là html (hãy nhớ dấu ngoặc!):
<div ng-controller="MyCtrl">
<div your-directive="{{ someObject.someVariable }}"></div>
<!-- use ng-bind instead of {{ }}, when you can to avoids FOUC -->
<div ng-bind="variable"></div>
</div>
Ngoài ra, hãy xem câu trả lời này: https://stackoverflow.com/a/12372494/1008519
Tham khảo cho vấn đề FOUC (nội dung chưa được định kiểu): http://deansofer.com/posts/view/14/AngularJs-Tips-and-Tricks-UPDATED
Đối với những người quan tâm: đây là một bài viết về vòng đời góc
ng-if="someObject.someVariable"
chỉ thị đơn giản (hoặc phần tử có chỉ thị làm thuộc tính) là đủ - chỉ thị chỉ có hiệu lực sau khi someObject.someVariable
được xác định.