passing different array variables to directive - javascript

In a controller I have defined two different arrays and I need to pass different arrays to directives, but the same item array is getting passed only.
Actually this is just snippets. In my actual code this directive I am using inside another.
Is that causing problem or any other way?
<div my-sticky tags="items" template_name="test2.html"></div>
<div my-sticky tags="kititems" template_name="test2.html"></div>
JS:
app.controller('MyCtrl', function($scope, $http) {
$scope.items = [
{ id: 18, text: '1' },
{ id: 28, text: '2' },
{ id: 38, text: '3' }
];
$scope.kititems = [
{ id: 0, text: '001' },
{ id: 028, text: '002' },
{ id: 038, text: '003' }
];
});
app.directive("mySticky", function($http, $compile) {
return {
restrict : "A",
scope : {
templateName: "#",
tags: "=",
},
templateUrl : function(el, attrs) {
return attrs.templateName;
},
controller : function($http, $scope, $element, $sce, $templateCache, $compile, $attrs) {
$scope.drawerStyle = {left: '140px'};
//$scope.CommonArray=$attrs.tags;
},
replace : false,
transclude : false,
link : function(scope, element, attrs) {
// change element just to show we can
}
};
});

Try this one
Working Demo
Inside your templateURL(test2.html) should like this i.e,
<div ng-repeat="tag in tags"> {{tag.id}} {{tag.text}} </div>
You might try to access items or kititems both are not in current scope because you have used isolated scope here.For clarity template used here instead of templateURL.
HTML Markup:
<div ng-controller="MyCtrl">
MyCtrl
<div my-sticky tags="items"></div>
<hr/>
<div my-sticky tags="kititems"></div>
</div>
angular modules
var app = angular.module("myApp",[]);
app.controller('MyCtrl', function($scope) {
$scope.items = [
{ id: 18, text: '1' },
{ id: 28, text: '2' },
{ id: 38, text: '3' }
];
$scope.kititems = [
{ id: 0, text: '001' },
{ id: 028, text: '002' },
{ id: 038, text: '003' }
];
});
app.directive("mySticky", function($http, $compile) {
return {
restrict : "A",
scope : {
templateName: "#",
tags: "=",
},
template :'<div ng-repeat="tag in tags"> {{tag.id}} {{tag.text}} </div>',
controller : function($http, $scope, $element, $sce, $templateCache, $compile, $attrs) {
$scope.drawerStyle = {left: '140px'};
// console.log($scope);
//$scope.CommonArray=$attrs.tags;
},
replace : false,
transclude : false,
link : function(scope, element, attrs) {
// change element just to show we can
}
};
});

Related

Recursive directive in angular js

I created a custom directive.
angular.module('menu',[])
.directive('Menu',function(){
return{
restrict:'E',
replace:'true',
scope:{
menuList:'=',
id:'#',
parentId:'#'
},
controller:function($scope){
},
template: `
<div ng-repeat="menuItem in menuList">
<a>{{menuItem.longDescription}}</a>
<div ng-if="menuItem.child.size() > 0 ">
<menu menu-list="menuItem.child"
id="menuItem.optionGroupId"
parent-id="menuItem.parentOptionGroupId">
</menu>
</div>
</div>
`
}
})
Menu items can have child list and if child list exist it should make menu recursively, but recursion is not happening.
(function() {
angular.module("menuTest", [])
.controller('testCtrl', function($scope) {
$scope.menu = [{
id: 1,
children: [{
id: 3
}]
},
{
id: 2,
children: [{
id: 4
},
{
id: 5
}
]
}
];
})
.directive("menu", function() {
return {
restrict: "E",
replace: true,
scope: {
menuList: '='
},
template: '<div ng-repeat="menuItem in menuList">{{menuItem.id}}<div ng-if="menuItem.children && menuItem.children.length>0" ><menu menu-list="menuItem.children"></menu></div><div>'
}
})
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="menuTest" ng-controller="testCtrl">
<menu menu-list="menu"></menu>
</div>

html is not compile on append new child in angular js

I am trying to insert a node dynamically, but the appended html is not getting compiled correctly.
This is the code on Fiddle.
<body ng-app="app">
<div ng-controller="appController">
{{tittle}}
<div name="name" ng-repeat="d in data" ng-click="click(d.id)" id="div{{d.id}}">{{d.id}} click me</div>
</div>
(function () {
var app = angular.module('app', []);
app.controller('appController', function ($scope, $compile) {
$scope.tittle = "test";
$scope.data = [{ id: 1, child: [{name:'renjith'}] }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }];
$scope.click = function (data, $element) {
debugger;
var scope = { id: "12" };
angular.element(document.querySelector("#div" + data)).append($compile("<div ngTransclude>{{d.id}}</div>")($scope.data));
}
});
})();

Nested directives not inheriting parent scope properly

Having a problem with nested directives and inheriting the scope from a parent. It happens that the scope I want to inherit from is an isolated scope. I've the code below
test.html
<div ng-controller="testCtrl as test">
<special-select data-selected-item="test.selectedThing">
<special-select-selected-item></special-select-selected-item>
</special-select>
</div>
app.js
angular
.module('testApp', ['special-inputs'])
.controller('testCtrl', [
function() {
this.items = [
{ id: 1, name: 'alex 1', displayName:"alex 1 dn", imageUrl: 'http://placehold.it/505x100' }
];
this.selectedThing = this.items[0];
this.test = function() {
console.log('test fn');
}
}
]);
special-inputs.js
angular
.module('special-inputs', [])
.directive('specialSelect', [
function() {
return {
restrict: 'E',
replace: true,
transclude: true,
template: '<div class="container" ng-transclude></div>',
scope: {
selectedItem: '='
},
link: {
pre: function(scope) {
console.log('parent link pre - ', scope.selectedItem);
},
post: function(scope) {
console.log('parent link post - ', scope.selectedItem);
}
}
}
}
])
.directive('specialSelectSelectedItem', [
function() {
return {
restrict: 'E',
replace: true,
transclude: true,
template: '<div class="selected" ng-transclude></div>',
scope: true,
link: {
pre: function(scope) {
console.log('child link pre - ', scope.selectedItem);
},
post: function(scope) {
console.log('child link post - ', scope.selectedItem);
}
}
}
}
])
As you can see the nested directive is trying to create it's own isolate scope but grab the "selectedItem" from the isolate scope of the parent.
The docs say it should inherit and transclusion is semi prototypical, so I'm wondering why it's not working. Thanks. Any help would be appreciated
UPDATE
I've updated the code to show the problem I'm having now. It seems that the scope item is set in the pre + post link functions on the parent, but never get put down to the child. The console outputs
2015-12-29 15:13:44.258 special-select.js:35 parent link pre - Object {id: 1, name: "alex 1", displayName: "alex 1 dn", imageUrl: "http://placehold.it/505x100"}
2015-12-29 15:13:44.258 special-select.js:64 child link pre - undefined
2015-12-29 15:13:44.260 special-select.js:67 child link post - undefined
2015-12-29 15:13:44.260 special-select.js:38 parent link post - Object {id: 1, name: "alex 1", displayName: "alex 1 dn", imageUrl: "http://placehold.it/505x100"}
I've tried using scope.$watch and attrs.$observe to populate the valu

Issue with scope of a custom directive

Hi I have a directive like,
mainApp.directive('myMenu',function(){
return {
restrict : 'E',
scope :{menuItems : "=menuItems"},
compile: function(element, attributes) {
var linkFunction = function($scope, element, attributes){
for (i = 0;i<$scope.menuItems.length;i++){
element.append('<li>'+$scope.menuItems[i].name+'</li>');
}
}
return linkFunction;
}
}
});
I am using it like below in my HTML
<my-menu menuItems="menuItems"></my-menu>
But in the console I am getting an error like
TypeError: Cannot read property 'length' of undefined
The problem could be that, then the linking phase is executed the menuitems may not be loaded so $scope.menuItems may be undefined.
A better solution could be
var mainApp = angular.module('my-app', [], function() {})
mainApp.controller('AppController', function($scope) {
$scope.menuItems = [{
name: 'one'
}, {
name: 'two'
}, {
name: 'three'
}, {
name: 'four'
}];
})
mainApp.directive('myMenu', function() {
return {
restrict: 'E',
scope: {
menuItems: "="
},
template: '<ul><li ng-repeat="item in menuItems">{{item.name}}</li></ul>'
}
});
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>
<div ng-app="my-app" ng-controller="AppController">
<my-menu menu-items="menuItems"></my-menu>
</div>
If you can't use template then
var mainApp = angular.module('my-app', [], function() {})
mainApp.controller('AppController', function($scope) {
$scope.menuItems = [{
name: 'one'
}, {
name: 'two'
}, {
name: 'three'
}, {
name: 'four'
}];
})
mainApp.directive('myMenu', function() {
return {
restrict: 'E',
scope: {
menuItems: "=menuItems"
},
link: function($scope, element, attributes) {
$scope.$watch('menuItems', function(value) {
element.empty();
angular.forEach(value, function(item) {
element.append('<li>' + item.name + '</li>');
});
});
}
}
});
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>
<div ng-app="my-app" ng-controller="AppController">
<my-menu menu-items="menuItems"></my-menu>
</div>
The Issue was with the name I used, like menuItems in directive should be equal to menu-items, solved the issue by repalcing the menuItems to menu.
use $scope.$eval(attributes.menuItems) inside compile function to get menuItems

Why doesn't directive work if I put name as an attribute rather than a tag?

In the example from the Angular documentation, a directive can be used by putting its name as an attribute in a <div>. The example given is
<div ng-controller="Controller">
<div my-customer></div>
</div>
with the js looking like
angular.module('docsSimpleDirective', [])
.controller('Controller', ['$scope', function($scope) {
$scope.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
}])
.directive('myCustomer', function() {
return {
template: 'Name: {{customer.name}} Address: {{customer.address}}'
};
});
However, in a similar example, over here, if I change the html code from <tree> to <div tree>, the code no longer works.
Why not?
The code from JS Fiddle:
<div ng-app="myapp">
<div ng-controller="TreeCtrl">
<tree family="treeFamily">
<p>{{ family.name }}</p>
</tree>
</div>
</div>
var module = angular.module('myapp', []);
module.controller("TreeCtrl", function($scope) {
$scope.treeFamily = {
name : "Parent",
children: [{
name : "Child1",
children: [{
name : "Grandchild1",
children: []
},{
name : "Grandchild2",
children: []
},{
name : "Grandchild3",
children: []
}]
}, {
name: "Child2",
children: []
}]
};
});
module.directive("tree", function($compile) {
return {
restrict: "E",
transclude: true,
scope: {family: '='},
template:
'<ul>' +
'<li ng-transclude></li>' +
'<li ng-repeat="child in family.children">' +
'<tree family="child">{{family.name}}</tree>' +
'</li>' +
'</ul>',
compile: function(tElement, tAttr, transclude) {
var contents = tElement.contents().remove();
var compiledContents;
return function(scope, iElement, iAttr) {
if(!compiledContents) {
compiledContents = $compile(contents, transclude);
}
compiledContents(scope, function(clone, scope) {
iElement.append(clone);
});
};
}
};
});
tree {
margin-left: 20px;
display: block;
}
The restrict option is used to specify how a directive can be invoked on the page. There are four different ways to invoke a directive, so there are four valid options for restrict:
'A' - attribute - <span ng-sparkline></span>
'E' - element - <ng-sparkline></ng-sparkline>
'C' - class - <span class="ng-sparkline"></span>
'M' - comment - <!-- directive: ng-sparkline -->
In your case its not working because it is defined as restrict 'E' - element.
It's because of the restrict option in the directive.
Here it is set to e which means to match only the element name.
More https://docs.angularjs.org/guide/directive

Categories