Accessing properties of directive's isolated scope from controller - angularjs

I'm trying to access the properties of my directive's isolated scope. Im slightly new to angularJS so I'm unsure if this is actually possible or not.
Below is my code:
angular.module('myModule').directive('myDirective', function() {
return {
restrict: 'EA',
require: 'ngModel',
scope: {
type: '=',
fName: '=',
lName: '=',
},
templateUrl: '...'
};
}
);
angular.module(myModule).controller('myCtrl', [
'$scope',
function($scope) {
$scope.openLink= function() {
if ($scope.type === 'member') { //Here is where I want to access the type from the scope of the directive!
$window.open('http://wwww.google.com, 'myWindow', 'menubar=0, width=600, height=680, scrollbars=yes, resizable=yes, top=180, left=350');
}
};
}
]);
I would appreciate if someone could assist.
Many thanks

Yes you can do that.you have to add 'type' property to your controller scope and you already passing 'type' to directive as value(refrence) and then set your 'type ' in directive either in link function or directive controller.
angular.module(myModule).controller('myCtrl', [
'$scope',
function($scope) {
$scope.type="";
$scope.openLink= function() {
if ($scope.type === 'member') { //Here is where I want to access the type from the scope of the directive!
$window.open('http://wwww.google.com, 'myWindow', 'menubar=0, width=600, height=680, scrollbars=yes, resizable=yes, top=180, left=350');
}
};
}
angular.module('myModule').directive('myDirective', function() {
return {
restrict: 'EA',
require: 'ngModel',
scope: {
type: '=',
fName: '=',
lName: '=',
},
templateUrl: '...',
controller:function($scope){
$scope.type="member";
}
};
}
);

Related

how to use $sce in Angular directive

Basically we would like to sanitize html data as soon I used $sce it does not work is there any alternate option to use instead $sce ?
app.directive('stack', ['$timeout', function($timeout) {
return {
restrict: 'A',
controller: 'StackController',
scope: {
onReady: '&?',
onChange: '&',
onDragStart: '&',
onDragStop: '&',
onResizeStart: '&',
onResizeStop: '&',
options: '='
},
link: function(scope, element, attrs, controller, $sce) {
var stack = controller.init(element, scope.options);
var serializeItems = function() {
const data = [];
$(element).children().each((index, item) => {
const $item = $($sce.trustAsHtml(item)).data('_stack');
data.push({
id: $item.id,
type: $($sce.trustAsHtml(item)).attr('type'),
position: [
$item.x,
$item.y,
],
size: [
$item.width,
$item.height,
],
});
});
return data;
}
}
};
}]);
Thank in advance please guide
Your injecting $sce in the wrong way:
app.directive('stack', ['$sce', function($sce){
return {
restrict: 'C',
link: function (scope, element, attrs) {
...$sce(your content) ...
}
}
}]);
Notice that the module should be injected to the directive, as opposed to being injected to the link function.
I would use $sce with a wrapping function, just to render stuff in the View/HTML, so, in
the controller:
scope.trustAsHtml(str) {
return $sce.trustAsHtml(str);
}
in the view/html:
<div>{{trustAsHtml(yourData)</div>

How siblings are sharing their scope under following directive structure

I have following directive structure.
<test-widget-body>
<test-task-list-filter>
</test-task-list-filter>
<test-task-list>
<test-datatable config="dtConfig" columns="dtColumns" api="dtApi"></test-datatable>
</test-task-list>
</test-widget-body>
Here are respective directives:
test-datatable
angular.module('testDatatable').directive('testDatatable', function () {
var directive = {
controller: 'testDatatableController',
restrict: 'E',
replace: true,
scope: {
config: '=',
columns: '=',
api: '=',
},
link: lnkFunction,
template: '<table class="table"></table>',
};
return directive;
}
testTaskList
angular.module('testTask').directive('testTaskList', function () {
return {
transclude: true,
restrict: 'E',
controller: 'testListController',
controllerAs: 'vm',
templateUrl: '/app/test/directives/test-list/test-list.html',
link: {
pre: preLink
}
};
function preLink(){
var dtColumns = [{
----
}];
var dtConfig =[];
var dtApi =[];
}
}
testTaskListFilter
angular.module('testTask').directive('testTaskListFilter', function () {
return {
restrict: 'E',
controller: 'testListFilterController',
templateUrl: '/app/test/directives/test-list/test-list-filter.html'
};
});
testWidgetBody
angular.module('testWidgetGrid').directive('testWidgetBody', function () {
return {
templateUrl: 'test.html',
link: function ($scope, element) {
}
}
Here I'm able to access dtConfig dtColumns dtApi objects inside testListFilterController controller.
How is this possible as <test-task-list-filter> and <test-task-list> are siblings.
Can anyone explain what is happening in this scenario.
Note: I'm able to access that object when I perform some click action not while directive rendering.
If you look at the declarations for testTaskListFilter directive and the testTaskList directive, neither of them have isolate scopes. You can declare isolate scopes by doing one of the following in the directive: scope: true or scope: {} (like in your testDatatable) directive.
Thus, any directive that does not declare its own scope inherits its parent's. So, testTaskListFilter and testTaskList are both using the same scope. This means that you're then able to
access dtConfig dtColumns dtApi objects inside testListFilterController controller
Here's the Angular wiki post for understanding scopes and scope inheritance

Can I use a Directive in the template function?

So this is a simple example i just wrote up for the sake of this question, I'm curious if I'm able to use a directive and pass in an object to the directive's attribute, all in the template, not templateUrl. I would think it would work something like this:
angular.module('myModule')
.directive('someDirective', function() {
return {
scope: {
u: '=',
},
template: '<avatar user="u"></avatar>',
};
});
Yes you can! And it doesn't matter the definition order.
app.directive("directive1", function() {
return {
restrict: 'E',
scope: {
u: '#'
},
template : "<h4>{{u}}</h4><directive2 user='{{u}}'></directive2>"
};
});
app.directive("directive2", function() {
return {
restrict: 'E',
scope: {
user: '#'
},
template : "<h1>{{user}}</h1>"
};
});
See it in action in this jsfiddle
Yes, it's easy to pass your state through scope attributes. Here's a plunkr that demonstrates the concept.
app = angular.module('app',[])
.directive('someDirective', function() {
return {
scope: {
u: '=',
},
template: '<avatar user="u"></avatar>',
};
}).directive('avatar', function() {
return {
scope: {
user: '=',
},
template: '<span>{{user.name}}</span>',
};
})

Directive function parameter is undefined

Directive Template URL:
<div class="filter-input" ng-click="changeVisualization('trocaparaeste')">
Directive:
app.directive('asideFilter', function() {
return {
restrict: 'E',
scope: {
categories: "=",
change: "&onChange",
changeVisualization: '&onChangeVisualization'
},
templateUrl: 'assets/directives/asideFilter/asideFilter.html',
controller: function($scope){
}
};
});;
Directive usage:
<aside-filter change-visualization="onChangeVisualization()"/>
Controller that im trying to get the parameter data:
$scope.onChangeVisualization = function(option) {
console.log('option', option);
}
SOLUTION:
Directive Template URL:
<aside-filter on-change-visualization="onChangeVisualization(option)"/>
Directive:
app.directive('asideFilter', function() {
return {
restrict: 'E',
scope: {
categories: "=",
change: "&onChange",
changeVisualization: '&onChangeVisualization'
},
templateUrl: 'assets/directives/asideFilter/asideFilter.html',
link: function(scope){
// pass 'option' variable so it can be used in the callback
scope.changeVisualization({ option: "worked!" });
}
};
});;
Directive usage:
<aside-filter change-visualization="onChangeVisualization(option)"/>
You have your names switched:
scope: {
// prefixed with 'on'
// so usage: <my-directive on-change-visualization="someFunc(option)"/>
changeVisualization: '&onChangeVisualization'
},
// example:
link: function($scope) {
scope.changeVisualization = scope.changeVisualization || angular.noop;
// pass 'option' variable so it can be used in the callback
scope.changeVisualization({ option: "worked!" });
}
And change your html to:
<!-- with the prefixed 'on-' -->
<aside-filter on-change-visualization="onChangeVisualization(option)" />
In your controller:
$scope.onChangeVisualization = function(option) {
console.log('option', option); // logs: 'option worked!'
}

How to access wrapped variables in a directive?

I have an object which consists of multiple arrays:
$scope.myArrays = {
array1: ['Pizza', 'Spaghetti'],
array2: ['Lasagne', 'Schnitzel']
};
Moreover, I have a custom directive to which I want to pass this object myArrays and bind those arrays to scope variables:
<my-directive my-data="myArrays"></my-directive>
myApp.directive('myDirective', function() {
return {
restrict: 'E',
scope: {
arrayOne: '=myData.array1',
arrayTwo: '=myData.array2'
},
link: function(scope, elem) {
// get access to scope.array1 and scope.array2
}
};
});
All together in a fiddle for you to play around!
Is there a way to bind the arrays directly or do I need to bind arrays: '=myArrays' and access them like arrays.array1?
Binding has to be one to one, you cannot do that. Yes, you will have to access the arrays inside your directive.
myApp.directive('myDirective', function() {
return {
restrict: 'E',
scope: {
myData: '='
},
link: function(scope, elem) {
scope.arrayOne = scope.myData.array1;
scope.arrayTwo = scope.myData.array2;
}
};
});
You can directly access scope.myData.array1 and scope.myDate.array2 inside the directive template if you dont have to process these arrays in the link function and get rid of it.
You could do this by just assigning them to scope fields:
myApp.directive('myDirective', function() {
return {
restrict: 'E',
scope: {
myData: '='
},
link: function(scope, elem) {
scope.arrayOne = myData.array1;
scope.arrayTwo = myData.array2;
}
};
});
However, I would recommeend to just bind the object and to get rid of the link-function. That way the directives code is a lot shorter, more readable, less "black magic" happens and the references inside the directive are more expressive:
myApp.directive('myDirective', function() {
return {
restrict: 'E',
scope: {
myData: '='
}
};
});
Then you can just reference it inside the directive with myData.array1. Replace the '=' with '=someName' to reference it with someName.array1
your HTML should be :
<my-directive arrayone="myData.array1" arraytwo="myData.array2"></my-directive>
and your directive :
myApp.directive('myDirective', function() {
return {
restrict: 'E',
scope: {
arrayOne: '=arrayone',
arrayTwo: '=arraytwo'
},
link:function(scope){
console.log('arrayOne :',scope.arrayOne);
console.log('arrayTwo :',scope.arrayTwo);
},
controller: function($scope) {
console.log('arrayOne :',$scope.arrayOne);
console.log('arrayTwo :',$scope.arrayTwo);
}
};
});
Demo
HTML-Partial:
<div ng-controller="MyCtrl">
<my-directive my-data="myArrays" array-one="myArrays.array1" array-two="myArrays.array2">
</my-directive>
</div>
Script:
angular.module('myApp', [])
.directive('myDirective', function() {
return {
restrict: 'E',
scope: {
arrayOne: '=',
arrayTwo: '='
},
link: function(scope, elem) {
// get access to scope.array1 and scope.array2
//console.log(scope.array1)
console.log(scope.arrayOne);
console.log(scope.arrayTwo);
}
};
})
.controller('MyCtrl', function($scope) {
$scope.myArrays = {
array1: ['Pizza', 'Spaghetti'],
array2: ['Lasagne', 'Schnitzel']
};
});

Resources