I have the example below.
HTML:
<body ng-controller="MainCtrl as MgtCtrl">
<p>Hello {{MgtCtrl.name}}!</p>
<p>Result is {{MgtCtrl.result}}!</p>
<output-content data="MgtCtrl.name" result="MgtCtrl.result"></output-content>
</body>
JavaScript:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
var MgtCtrl = this;
MgtCtrl.name = 'World';
MgtCtrl.result = "no";
MgtCtrl.changeLabel = function() {
alert('changeLabel');
MgtCtrl.result = 'yes';
}
});
app.directive('outputContent', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'outputContent.html',
scope: {
data: '=',
changeLabel: '&',
result: '='
},
controller: 'MainCtrl',
controllerAs: 'MgtCtrl'
};
});
ouputContent.html:
<div>
{{data}}
<button ng-click="MgtCtrl.changeLabel()">Change</button>
</div>
Plunker is: http://plnkr.co/edit/BW8VDyCaRnRgxE8I9JJy
I would like the result to be 'yes' when I click on the 'Change' button.
It doesn't work because of the named controller.
Could you please explain to me how to write the directive to do so ?
Regards.
You never was binding the scope variables to the named controller in the directive.
You must add the attribute bindToController: true to the directive definition like this plunker:
http://plnkr.co/edit/2QdnkpeuTM6adG9KoyJT?p=preview
Directive code:
app.directive('outputContent', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'outputContent.html',
scope: {
data: '=',
changeLabel: '&',
result: '='
},
controller: 'MainCtrl',
controllerAs: 'MgtCtrl',
bindToController: true
};
});
This go to add the data and result binding to the respective directive controller.
I think in this case you don't need to specify controller in the directive.
app.directive('outputContent', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'outputContent.html',
scope: {
data: '=',
changeLabel: '&',
result: '='
}
};
});
Also html shoul be updated:
<body ng-controller="MainCtrl as MgtCtrl">
<p>Hello {{MgtCtrl.name}}!</p>
<p>Result is {{MgtCtrl.result}}!</p>
<output-content data="MgtCtrl.name" result="MgtCtrl.result" change-label="MgtCtrl.changeLabel()"></output-content>
</body>
Related
I use directive:
return {
restrict: 'E',
scope: {
isread: "=isread"
,....
templateUrl: 'list.html',
Where list.html is:
<span ng-show="isread"></span>
And parent trmplate from where I call directive:
<div class="top-menu" ng-controller="NotificationController">
<notification-list isread="is_read"></notification-list>
</div>
And NotificationController:
scope.makeRead = function() {
$scope.is_read = true;
}
Why when I change $scope.is_read = true; in controller it is not changed in directive in variable isread?
return {
restrict: 'E',
scope: {
isread: "="
,....
templateUrl: 'list.html',
I don't have access to the object which I'm passing it inside my directive.
// inside dialogController
showAlert(ev) {
this.mdDialog.show({
template:"<loader my-master="+this.masterCtrl+"></loader>"
});
// when debugging, I saw this.masterCtrl is exist as Object
//inside loader Controller:
export function loader() {
'ngInject';
let directive = {
templateUrl: "app/components/excelLoader/loader.html",
controller: loaderController,
controllerAs: 'vm',
scope: {
words: '=',
master:'=myMaster'
},
replace: true,
bindToController: true,
link: linkFunc
};
function linkFunc(scope, element, attr, ctrl) {
let vm = scope.vm;
ctrl.master=attr.myMaster;
}
return directive;
}
class loaderController {
constructor() {
'ngInject';
console.log(this.master); //prints string "this.masterCtrl" instead of the Object!
}
}
What is the correct way to pass this.masterCtrl from dialogController into loader directive and how to use access it in the loader directive?
Is this what you want? - CodePen
Markup
<div ng-controller="MyController as vm" ng-cloak="" ng-app="app">
<md-button class="md-primary md-raised" ng-click="vm.openDialog($event)">
Dialog
</md-button>
</div>
JS
angular.module('app',['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])
.controller('MyController', function($scope, $mdDialog) {
var vm = this;
vm.testObject = {test: "blah"};
vm.openDialog = function(ev) {
$mdDialog.show({
controller: 'DialogController',
controllerAs: 'DialogCtrl',
template: '<loader my-master="vm.testObject"></loader>',
parent: angular.element(document.body),
scope: $scope,
preserveScope: true,
targetEvent: ev,
clickOutsideToClose:true
});
};
})
.controller('DialogController', function($scope, $mdDialog) {
})
.directive("loader", loader);
function loader() {
return {
template: "<div>Loader directive - {{vm.master.test}}</div>",
controller: loaderController,
controllerAs: 'vm',
scope: {
words: '=',
master:'=myMaster'
},
replace: true,
bindToController: true,
};
function loaderController ($scope) {
console.log($scope.vm.master);
}
}
In your link function, assign ctrl.master = scope.master; attr.myMaster will read the attribute value from the html tag and will be a string. scope.master will be evaluated by angular.
I am facing issue while rendering directive inside nginit method.
first directive :
Controller :
$scope.addDetails(asset) {
asset.label = "<div window></div>";
};
return {
restrict: "EA",
scope: true,
controller: "demoController",
controllerAs: "vms",
template:
"<div data-ng-repeat = 'data in vms.details' ng-init='vms.addDetails(data);'" +
</div>"
};
window directive:
return {
restrict:"AE",
templateURL: "infowindow.html"
};
With the below approach it worked with me we shouldn't do any complex logic(DOM rendering) when we use ng-repeat with ng-init. if so we need to construct the directive after the data is rendered.
$scope.details= {asset:1,description:"sample text"};
$scope.addLabel(asset) {
asset.label = "sample text to be shown in other directive";
};
return {
restrict: "EA",
bindToController: {details:'='}
scope: true,
controller: "demoController",
controllerAs: "vms",
template:
"<div data-ng-repeat = 'data in vms.details' ng-init='vms.addLabel(data);'" +
"<div window label-text=data.label></div>" +
</div>"
};
window directive:
return {
restrict:"AE",
bindToController:{labelText: '#'},
scope:true,
templateURL: "infowindow.html"
};
infowindow.html
<div>{{vms.labelText}}</div>
I have the example below:
HTML:
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<p>Result is {{result}}!</p>
<output-content data="name"></output-content>
</body>
JavaScript:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.result = "no";
$scope.changeLabel = function() {
$scope.result = 'yes';
}
});
app.directive('outputContent', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'outputContent.html',
scope: {
data: '=',
result: '='
},
controller: 'MainCtrl'
};
});
outpuContent.html:
<div>
{{data}}
<button ng-click="changeLabel()">Change</button>
</div>
Plunker is: http://plnkr.co/edit/uzSrGcyQLeRNEIH7IXBf
I would like the result to be 'yes' when I click on the 'Change' button.
It doesn't work.
Could you please explain to me how to write the directive to do so ?
Regards.
You define variable in directive scope, but do not pass it. Just pass
"result" into directive. E.g:
<output-content data="name" result="result"></output-content>
I forked your plunkr: http://plnkr.co/edit/12FXjUsVdPXhPIQ1mlHt?p=preview
Hope it helpful.
In directive, delete scope . Now like This.. this will be work..
app.directive('outputContent', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'outputContent.html',
controller: 'MainCtrl'
};
});
Scope is not needed. Kindly delete the scope.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.result = "no";
$scope.changeLabel = function() {
$scope.result = 'oh yeah';
}
});
app.directive('outputContent', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'outputContent.html',
controller: 'MainCtrl'
};
});
Here is the code, ideally i should see
parent: true
when I click the toggle
However, it doesn't work
Here is the plunker
<body ng-controller="MainCtrl">
<button type="button" ng-click='isParentShown= !isParentShown' >Toggle</button>
<div><span>Controller-isParentShown: {{isParentShown}}</span></div>
<parent isShown='isParentShown'></parent>
</body>
var app = angular.module('plunker', []).directive('parent',function(){
return {
restrict: 'E',
replace: true,
scope: {
isShown: '='
},
template: '<span>Parent: {{isShown}}</span>'
};
}).directive('child',function(){
return {
restrict: 'E',
replace: true,
template:'<span>Child: {{isChildShown}}</span>',
scope: {
isChildShown: '#'
}
};
});
app.controller('MainCtrl', function($scope) {
$scope.isParentShown = false;
});
The problem is in the casing of the attributes, if you define a isShown binding, it's expecting a is-shown or is:shown attribute. Here's the fixed plunker: http://plnkr.co/edit/UOigth