你好我想我不明白双向数据绑定是什么。首先是代码:
Simulation sim = new Simulation();
“=”是否意味着外部范围的变化会因数据绑定而传播?或不?因为我获取$资源,它当然是在获取它之后定义的,但是“属性”仍未定义。那有什么不对?
编辑:期望的行为是sim
模板中的ng-class工作
编辑:plunker:https://plnkr.co/edit/drXxyMpd2IOhXMWFj8LP?p=preview
答案 0 :(得分:2)
您遗漏了transclude
选项的重要内容:包装内容绑定到 OUTER 范围,而不是指令的范围。
那么,这里是编译后范围绑定在你的案例中的样子:
<div ng-controller="CompanyDetailController">
<mup-stage-buttons property="company.stage" action="setStage"> <-- even though the 'property' is bound correctly, it is not available below due to transclusion -->
<span ng-transclude>
{{company.stage}} <!-- CompanyDetailController $scope available here due to transclusion, 'property' is not available! -->
<mup-stage-button property="company.stage" value="0">
<!-- directive's scope here, binding to the outer scope's 'company.stage' can be used here -->
{{property}} - {{value}} <!-- this will work -->
<label ng-class="property === value ? 'active' : 'btn-on-hover' " class="btn {{btnClass}}" ng-click="changeStage(value)">
<div ng-transclude>
<!-- transcluded content here, bound to the CompanyDetailController $scope -->
not working ng-class 0
</div>
</label>
</mup-stage-button>
</span>
</mup-stage-buttons>
</div>
因此,要使代码正常工作(Plunk),仅将property
映射到子指令的company.stage
就足够了。
<强>更新强>
为了避免重复对子指令的property="company.stage"
绑定并分别通过父指令和子指令的控制器和链接函数传递数据,您应该使用wrapping object
作为范围属性,这样你就可以通过引用传递给那个对象了。对象范围的任何更改都将可用于子范围,因为它们将引用该对象,这称为dot notation
:
CompanyDetailController:
$scope.vars = {};
this.getCompany = function () {
$scope.vars.company = $scope.company = {stage: 0};
};
然后将vars
属性绑定到父指令的范围:
// ...
scope: {
vars: '=',
},
controller: function($scope) {
this.vars = $scope.vars;
}
// ...
然后将vars
的引用放到子指令的范围:
// ...
link: function(scope, element, attrs, mupStageButtonsCtrl, transclude) {
scope.vars = mupStageButtonsCtrl.vars;
}
// ...
最后可以在子指令的视图中访问它:
<label ng-class="vars.company.stage === value ? 'active' : 'btn-on-hover'">...</label>
这样就不需要在子指令实例上重复绑定了。
Plunk已更新。
答案 1 :(得分:0)
在javascript中
基元按值传递,对象通过“副本传递” 参考”。
使用$ watch的解决方案:
.directive('mupStageButtons', function() {
return {
transclude: true,
template: '<span ng-transclude></span>',
replace: true,
scope: {
property: "=",
action: "="
},
controller: function($scope) {
that = this;
$scope.$watch('property', function(newValue){
that.property = newValue;
/***Refresh this.property (normal assignment would only copy value,
it would not behave as a reference to desired transcluded property)***/
});
this.changeStage = $scope.action;
},
};
})
.directive('mupStageButton', function() {
return {
transclude: true,
templateUrl: '/static/templates/directives/StageButton.html',
require: '^^mupStageButtons',
scope: {
value: "=",
btnClass: "@",
},
link: function(scope, element, attrs, mupStageButtonsCtrl, transclude) {
scope.btnCtrl = mupStageButtonsCtrl;
scope.changeStage = mupStageButtonsCtrl.changeStage;
}
};
})
$ watch旁边的一个重要部分也是链接功能:
scope.btnCtrl = mupStageButtonsCtrl;
我们无法做到
scope.property = mupStageButtonsCtrl.property;
因为它只是复制值,当它在ctrl中改变时,它在child指令中不会改变。 所以我们为scope.btnCtrl分配ctrl引用,它可以工作。 儿童指令的模板:
<label ng-class="btnCtrl.property === value ? 'active' : 'btn-on-hover' " class="btn {{btnClass}}" ng-click="changeStage(value)">
<div ng-transclude></div>
</label>
现在我可以根据需要使用指令 - 只传递像company.stage
这样的属性,这样指令就不需要知道属性名称(阶段)了。
<mup-stage-buttons property="company.stage" action="setStage">
<mup-stage-button value="0" btn-class="btn-default-grey">
Stage 0
</mup-stage-button>
</mup-stage-buttons>