วิธีที่ง่ายที่สุดในการส่งผ่านตัวแปรขอบเขต AngularJS จากคำสั่งไปยังคอนโทรลเลอร์คืออะไร ตัวอย่างทั้งหมดที่ฉันเห็นดูซับซ้อนมากไม่มีวิธีใดที่ฉันสามารถเข้าถึงคอนโทรลเลอร์จากคำสั่งและตั้งค่าตัวแปรขอบเขตได้หรือไม่?
วิธีที่ง่ายที่สุดในการส่งผ่านตัวแปรขอบเขต AngularJS จากคำสั่งไปยังคอนโทรลเลอร์คืออะไร ตัวอย่างทั้งหมดที่ฉันเห็นดูซับซ้อนมากไม่มีวิธีใดที่ฉันสามารถเข้าถึงคอนโทรลเลอร์จากคำสั่งและตั้งค่าตัวแปรขอบเขตได้หรือไม่?
คำตอบ:
แก้ไขเมื่อ 2014/8/25: นี่คือที่ที่ฉันแยกมัน
ขอบคุณ @anvarik
นี่คือJSFiddle ฉันลืมว่าฉันคีบมันไว้ที่ไหน แต่นี่เป็นตัวอย่างที่ดีที่แสดงให้คุณเห็นความแตกต่างระหว่าง = และ @
<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;
}
}]);
ฉันมีปัญหากับเรื่องนี้มากมายและไม่สามารถทำให้มันทำงานได้แม้จะมีตัวแปรที่กำหนดไว้"="
ในขอบเขตก็ตาม ต่อไปนี้เป็นสามวิธีขึ้นอยู่กับสถานการณ์ของคุณ
ฉันพบว่าตัวแปรไม่ได้รับการประเมินโดยเชิงมุม แต่เมื่อส่งผ่านไปยังคำสั่ง ซึ่งหมายความว่าคุณสามารถเข้าถึงและใช้งานได้ในเทมเพลต แต่จะไม่อยู่ในลิงก์หรือฟังก์ชันตัวควบคุมแอปเว้นแต่เราจะรอให้มีการประเมิน
หากตัวแปรของคุณกำลังเปลี่ยนแปลงหรือถูกดึงมาจากคำขอคุณควรใช้$observe
หรือ$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);
}
});
}]);
และนี่คือ html (จำวงเล็บไว้!):
<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>
โปรดทราบว่าคุณไม่ควรตั้งค่าตัวแปรให้"="
อยู่ในขอบเขตหากคุณกำลังใช้$observe
ฟังก์ชัน นอกจากนี้ฉันพบว่ามันส่งผ่านวัตถุเป็นสตริงดังนั้นหากคุณกำลังส่งผ่านวัตถุให้ใช้โซลูชัน # 2หรือscope.$watch(attrs.yourDirective, fn)
(หรือ# 3หากตัวแปรของคุณไม่เปลี่ยนแปลง)
หากตัวแปรของคุณถูกสร้างขึ้นในเช่นคอนโทรลเลอร์อื่นแต่เพียงแค่ต้องรอจนกว่าเชิงมุมจะได้รับการประเมินก่อนที่จะส่งไปยังตัวควบคุมแอปเราสามารถใช้$timeout
เพื่อรอจนกว่าจะ$apply
มีการทำงาน นอกจากนี้เราจำเป็นต้องใช้$emit
เพื่อส่งไปยังตัวควบคุมแอปขอบเขตหลัก (เนื่องจากขอบเขตแยกในคำสั่ง):
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;
});
}]);
และนี่คือ html (ไม่มีวงเล็บ!):
<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>
หากตัวแปรของคุณไม่เปลี่ยนแปลงและคุณจำเป็นต้องประเมินค่าในคำสั่งของคุณคุณสามารถใช้$eval
ฟังก์ชัน:
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);
}
});
}]);
และนี่คือ html (จำวงเล็บไว้!):
<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>
ลองดูคำตอบนี้: https://stackoverflow.com/a/12372494/1008519
ข้อมูลอ้างอิงสำหรับปัญหา FOUC (flash of unstyled content): http://deansofer.com/posts/view/14/AngularJs-Tips-and-Tricks-UPDATED
สำหรับผู้สนใจ: นี่คือบทความเกี่ยวกับวงจรชีวิตเชิงมุม
ng-if="someObject.someVariable"
ในการสั่ง (หรือองค์ประกอบที่มีคำสั่งเป็นแอตทริบิวต์) จะเพียงพอ - เตะสั่งในเฉพาะหลังจากที่someObject.someVariable
มีการกำหนด