[英]Angular two-way data binding isolate scope directive but property is undefined?
您好,我想我不明白什么是雙向數據綁定。 首先是代碼:
.directive('mupStageButtons', function() {
return {
transclude: true,
template: '<span ng-transclude></span>',
replace: true,
scope: {
property: "=",
action: "="
},
controller: function($scope) {
console.log($scope); //I can see the property of $scope defined in console
console.log($scope.property); //undefined
this.property = $scope.property;
this.changeStage = $scope.action; //anyway this is ok
},
};
})
.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.property = mupStageButtonsCtrl.property;
scope.changeStage = mupStageButtonsCtrl.changeStage;
}
};
})
//html
<mup-stage-buttons property="company.stage" action="setStage">
<mup-stage-button value="0" btn-class="btn-default-grey">
</mup-stage-button>
</mup-stage-buttons>
//controller for that html ^^^
.controller('CompanyDetailController', function($scope, $stateParams, Company){
Company.query ({
id : $stateParams.companyId
}, function (data) {
$scope.company = new Company(data);
});
}
//template for <mup-stage-button>
<label ng-class="property === value ? 'active' : 'btn-on-hover' " class="btn {{btnClass}}" ng-click="changeStage(value)">
<div ng-transclude></div>
</label>
“ =”是否意味着外部范圍的更改將由於數據綁定而傳播? 或不? 因為我獲取了一個$ resource,它當然是在獲取后定義的,但是“屬性”仍然是未定義的。 那怎么了?
編輯:所需的行為是<mup-stage-button>
模板中的ng-class工作
編輯:朋克: https ://plnkr.co/edit/drXxyMpd2IOhXMWFj8LP ? p = preview
您缺少有關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
就足夠了。
UPDATE
為避免在子指令上重復執行property="company.stage"
綁定,並分別通過父指令和子指令的controller和link函數傳遞數據,應將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
的引用放到child指令的作用域中:
// ...
link: function(scope, element, attrs, mupStageButtonsCtrl, transclude) {
scope.vars = mupStageButtonsCtrl.vars;
}
// ...
並最終在child指令的視圖中對其進行訪問:
<label ng-class="vars.company.stage === value ? 'active' : 'btn-on-hover'">...</label>
這樣,就無需在子指令實例上重復綁定。
Plunk已更新。
在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指令中此處不會更改。 因此,我們將ctrl引用分配給scope.btnCtrl即可。 子指令的模板:
<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>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.