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>
Related
If I have two directives, one that's a table, and one that's a row. In this case the row is the same each time, and I just want to have it displayed twice in the index.html. <table-row> works in the index.html, but <table> does not why?
i.e.:
.directive('table', function() {
return {
restrict: 'E',
scope: {},
controller: 'table-ctrl',
controllerAs: 'ctrl',
bindToController: true,
template:`
<div>
<table-row></table-row>
<table-row></table-row>
</div>`
};
});
Table Row:
.controller('TableRowCtrl', function() {
this.toggle = function() {
this.toggleBool = !this.toggleBool;
}
//
this.toggleBool = false;
})
.directive('TableRow', function() {
return {
scope: {},
restrict: 'E',
replace: true,
controller: 'TableRowCtrl',
controllerAs: 'ctrl',
bindToController: true,
template: `
<div>
<span>Object</span>
<span>
<img ng-click="ctrl.toggle()" src="jpeg file" />
</span>
<span ng-if="ctrl.toggleBool"> Print </span>
</div>`
};
});
If table-row is the other directive that does everything and its controller is also what runs on clicks etc, how would I link in the table-row directive so that the table directive template works, and will call table-row multiple times.I would like to continue using the ControllerAs syntax instead of $scope.
It doesn't matter if you want to use controllerAs or not. From your code table directive has isolate scope and suppose if you want to iterate through table-row items by using ngRepeat directive it should be isolate scope as well.
Remember that every ngRepeat's item has own scope
For example:
.directive('table', function() {
return {
restrict: 'E',
scope: {},
controller: 'table-ctrl',
controllerAs: 'ctrl',
bindToController: true,
template:
<div ng-repeat="item in ctrl.items">
<table-row item="item"></table-row>
</div>`
};
});
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',
Got two directives. One is a "subdirective"
Main:
.directive('materialDropdown', function() {
// Input to directive
return {
scope: {
//'personalDb': '=',
},
transclude: true,
controllerAs: 'vm',
bindToController: true,
controller: function(){
console.log('material directive fires')
},
template: '<select></select>',
restrict: 'E',
link: function(){}
};
});
sub:
.directive('materialSizeDropdown', function() {
// Input to directive
return {
require: '^^materialDropdown',
controllerAs: 'vm',
transclude: true,
bindToController: true,
controller: function(){
console.log('hello')
},
template: '<h1>fire</h1>',
restrict: 'E',
link: function(){}
};
Markup:
<material-dropdown>
<material-size-dropdown></material-size-dropdown>
</material-dropdown>
The materialSizeDropdown is not shown in the markup, and the controller is not fired either.
How do I solve this?
You're using the template option on your materialDropdown directive which will use for rendering. So your nested directive will never shown. And a <h1> in a <select> would not be valid.
I'm relatively new to AngularJS and working on creating tabs in a page. Till now I have resolved my problems with angularjs by searching a lot on internet but I can't resolve this. Hope anyone can help me with ideas and better knowledge of angularjs.
I have two custom directives tabset and tab. 'Tabset' is the directive to maintain the tabs and 'tab' is for a single tab.
app.directive('tabset', function() {
return {
restrict: 'E',
transclude: true,
templateUrl: 'tabset.html',
bindToController: true,
scope: {},
controller: function($scope){
$scope.tabs = [];
this.addTab = function(tab) {
$scope.tabs.push(tab);
}
console.log("In tabset controller");
},
link : function(scope){
console.log("In the tabset link");
}
}
});
//Custom Directive for the tab controls
app.directive('tab', function() {
return {
restrict: 'E',
transclude: true,
template: '<h2>Welcome to Stackoverflow</h2> <div role="tabpanel" ng-transclude></div>',
require : '^tabset',
scope: {},
link : function(scope, elem, attr, tabsetCntrl) {
tabsetCntrl.addTab(scope);
console.log("In the tab link");
}
}
});
I call these directives in my HTML page as shown below:
<tabset>
<tab>
This is one tab
</tab>
<tab>
This is another tab
</tab>
</tabset>
But, when I run the code, the link function of the tab directive is not running. The 'require : ^tabset' option gets the controller from the tabset, but the link function of the tab directive is not working.
Try adding controllerAs: '$ctrl' to your tabset directive.
Like:
angular.module('app').directive('tabset', function() {
return {
restrict: 'E',
transclude: true,
templateUrl: 'tabset.html',
bindToController: true,
controllerAs: '$ctrl', // <---- HERE
scope: {},
controller: function($scope){
$scope.tabs = [];
this.addTab = function(tab) {
$scope.tabs.push(tab);
}
console.log("In tabset controller");
},
link : function(scope){
console.log("In the tabset link");
}
}
});
Tested
Further info found by checking the error seen in console here
Prudhvee, take a look at this demo i did to understand the making of angular tabs using nested directives.
app.directive('tabset', function() {
return {
restrict: 'E',
transclude: true,
scope: {},
controller: [ "$scope", function($scope) {
var panes = $scope.panes = [];
$scope.select = function(pane) {
angular.forEach(panes, function(pane) {
pane.selected = false;
});
pane.selected = true;
}
this.addPane = function(pane) {
if (panes.length == 0) $scope.select(pane);
panes.push(pane);
}
}],
template:
'<div class="tabbable">' +
'<ul class="nav nav-tabs">' +
'<li ng-repeat="pane in panes" ng-class="{active:pane.selected}">'+
'{{pane.title}}' +
'</li>' +
'</ul>' +
'<div class="tab-content" ng-transclude></div>' +
'</div>',
replace: true
};
});
app.directive('tab', function() {
return {
require: '^tabset',
restrict: 'E',
transclude: true,
scope: { title: '#' },
link: function(scope, element, attrs, tabsCtrl) {
tabsCtrl.addPane(scope);
},
template:
'<div class="tab-pane" ng-class="{active: selected}" ng-transclude>' +
'</div>',
replace: true
};
})
http://plnkr.co/edit/BJWWw2?p=preview
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>