So I have an nvd3 graph in my index.html whose height is set to {{varyingHeight}} like so (code snippet):
<nvd3-line-plus-bar-chart data="data"
showXAxis="true" showYAxis="true"
tooltips="true" interactive="true"
showLegend="true"
height='{{varyingHeight}}'
>
</nvd3-line-plus-bar-chart>
Now in my directive, I have a code which identifies when the height change takes place, and what the new height is:
app.directive('test', function () {
return {
restrict: 'EA',
scope: {},
link: function (scope, element) {
scope.$on('split.resize', function() {
console.log('I got resized');
console.log(element.height());
});
}
};
});
In my controller, I now want to be able to set the new height like so:
$scope.$apply(function(){
$scope.varyingHeight = h;
})
I'm new to angularjs so I can't figure what the best way is to do this. I have seen answers which show how to do this the other way round, i.e from the controller to the directive but this hasn't helped me. How do I pass a element.height() to variable h from the directive to the controller? Or is my code structured wrong in the first place?
You do it by binding the height attribute to the value passed from the controllers scope. Here's an example: http://jsbin.com/vapipizu/1/edit
The important part is that you replace height="{{varyingHeight}}" with height="varyingHeight" and that your directive binds the height attribute like this:
scope: {
height: '='
}
I also faced this issue, I resolved it by passing the height as attribute to the directive
My sample directive
App.directive('aBc',function () {
return {
restrict : 'AE',
scope : {
gridHeight : '#'
},
template : '<div style= "height : {{gridHeight}}px" >'
+'<p>sdtyhdrtydrt-- {{gridHeight}} </p>'
+ '</div>'
};
});
pass the height through directive tag
directly you can pass the height
<div a-bc grid-height="200"></div>
<div a-bc grid-height="500"></div>
<div a-bc grid-height="1000"></div>
or you can set it from your controller
<div a-bc grid-height="someHeight"></div>
initialize someHeight in controller like
$scope.someHeight = 500;
Related
app.directive('hidefileId',['$document','documentService',function($document,documentService){
return{
scope: false,
restrict: 'AE',
link : function($scope,element,attrs){
element.on('click',function(e){
angular.element('#fileId').removeClass("errorhilight");
angular.element('#docerrormsg').html('');
})
}
}
}]);
I have many directives in my js controller, when I use the following directive I am getting the parent scope in
$scope.$parent.$parent.$parent.$parent.// here I am getting the scope of my controller.
even I use scope: false, it is creating new scope.
I want to use the my controller scope only
You can use the require directive option. This will give you access to a parent controller(s). The directive with throw an exception if the controller(s) can not be found. You will have access to anything you put on that controller. This is a great method to use if you need a parent child relationship where a child directive needs access to the parent. It also allows for more modular code.
e.g.
I have written a table directive with an exposed API to add formatting to cells. This is very useful as you can write many additional table directives that can be used interchangeably throughout an application. As an example I will show you a child HoverTitle directive that uses the parent table directive to add a hover tooltip in a given cell.
function HoverTitle(CellProcessService){
'ngInject';
return{
require: '^cTable', // require c-table
link: function(scope, element, attrs, cTable){
cTable.addCellRenderProcess(renderCell, CellProcessService.priorities["HOVER-TITLE"]);
function renderCell(curr, column, row){
if(angular.isFunction(cTable.hoverClass)){
var hoverTitle = cTable.hoverClass(row, curr, column);
if(hoverTitle){
var placement = cTable.placement || 'right';
var tag = column.link ? "span" : 'a'
return '<' + tag + ' tooltip-placement="'+placement+'" uib-tooltip="' + hoverTitle + '">' + curr +'</ ' + tag + '>';
}
}
return curr;
}
}
}
}
Here is how it could be used:
<c-table
table-sort
hover-title
data="$ctrl.data"
columns="$ctrl.columns">
</c-table>
https://docs.angularjs.org/guide/directive#creating-directives-that-communicate
First what I want:
I have a series of thumbnails. When I click on one, I want that specific thumbnail to be shown in a bigger div, with its description. (For later: should be animated).
Now I have the directive and the controller, but I don't know how to set the appropriate variable!
So some code:
First HTML: here is the root .jade file for this section. I have a directive called product.
section
.detail-view(ng-show="vm.showDetail")
.prod-desc(ng-bind="vm.detailPic")
.prod-img(ng-bind="vm.detailDesc")
product.col-xs-12.product_tile(ng-repeat="item in vm.products", item="::item")
As you can see, the product directive is part of an ng-repeat; for this reason, the div I want to show the resized image is outside the iteration (.detail-view).
The product directive:
'use strict';
ProductDirective.$inject = ['ShopCart', '$animate', 'User'];
function ProductDirective(ShopCart, $animate, User) {
return {
restrict: 'E',
scope: {
item: '='
},
template: require('./product.html'),
link: link
};
function link(scope, element) {
scope.toggleDetails = toggleDetails;
}
function toggleDetails() {
if (!scope.isSelected && isBlurred()) return;
scope.vm.detailPic = scope.item.photo;
scope.vm.detailDesc = scope.item.prod_description;
scope.vm.isSelected = !scope.isSelected;
scope.showDetail = !scope.showDetail;
var action = scope.isSelected ?
}
}
Now the div I want to update with the image in big is outside the iteration - and hence outside the scope of the directive. How can I set the value of showDetail, showDesc and showPic?
As I am using controllerAs with value vm, I thought I could just do scope.vm.detailPic = scope.item.photo;, as in other solutions I have seen that when setting a property on a root object, it would be propagated...but I get
Cannot set property 'detailPic' of undefined
For now, what works (but looks a bit odd to me) is this, in toggleDetails()
scope.$parent.$parent.vm.detailPic = scope.item.photo;
scope.$parent.$parent.vm.detailDesc = scope.item.prod_description;
scope.$parent.$parent.vm.showDetail = !scope.$parent.$parent.vm.showDetail
I set a progress in my app
I want to controll The progress in angular's directive
but how can I change data-value and data-total in directive's link func?
app.html
<div class="ui indicating small progress" data-value="39" data-total="50" plan-progress>
<div class="bar">
<div class="progress"></div>
</div>
</div>
In this html, I want change data-value and data-total
I try this:
app.js
todoApp.directive('planProgress', function() {
return {
link: function(scope, elem, attrs) {
attrs.value = 10
attrs.total = 20
elem.progress();
}
};
});
But it doesn't work
so I want to know how to change it in my directive?
Use attrs.$set() in your link function and recompile the element. Also, don't forget to inject the $compile service to your directive.
In your html you've added the directive as an attribute but didn't mention it in the restrict value in your directive definition. You need to mention it in directive definition.
See the code bellow:
todoApp.directive('planProgress', function($compile) {
return {
restrict: 'A',
link: function(scope, elem, attrs) {
attrs.$set('value', 10);
attrs.$set('total', 20);
$compile(elem)(scope);
}
};
});
Simply use :
attrs["data-value"] = 10;
attrs["data-total"] = 20;
You don't want to use attrs.data-total = 20 because the - will force a subtraction.
It's always legal in javascript to use x[keyName] instead of x.keyName, and you must use this second notation when keyName is a strange key such as **$^ùjsls* or data-value. A more useful case is when the key is a variable.
On last thing : as you do, you will always rewrite the coder's inputs. It may have sense, but it's not very elegant.
to know the width of div
i want to know the width of the within the template ,and store in the variable how can i achieve that
pp.directive('skillSlider',function()
{
return{
template:'<div class="progress"></div>'
}
});
----------
how to calculate the width of the div inside the directive template
You can do this with angular.element e.g.:
angular.element(document.getElementById(id)).clientWidth;
angular.element(document.querySelectorAll('.class')[0]).clientWidth;
or if you have jQuery loaded
angular.element($('#id').width();
angular.element($('.class')[0]).width();
you can have the link function to get access to the element using which you can get the width of the div.
pp.directive('skillSlider',function()
{
return{
template:'<div class="progress"></div>',
link:function (scope, element, attrs) {
console.log(element.width());
})
}
});
How to attach arbitrary data to an html element declaratively, and retrieve it.
Please see the code. http://plnkr.co/edit/sePv7Y?p=preview
Angular has the jQuery data() support.
So, I want to attach data to each li element (say _data = node ) in the template, and later on to retrieve it using
var li = elm[0]....
console.log('li-', li.data('_data'))
li - {id:1}
Code:
'use strict';
var app = angular.module('Directives', []);
app.controller('MainCtrl', function ($scope) {
$scope.data = [
{id:1}, {id:2}, {id:3}
];
});
app.directive('test', function ($timeout) {
return {
template: '<li class="ch" ng-repeat="node in data">' +
'<span class="span2">' + 'id - {{node.id}}' + '</span>' +
'</li>',
restrict: 'A',
link: function (scope, elm, attrs) {
console.log(elm[0].children);
}
};
});
Edit:
Updated the code with how I like to set data.
template: '<li class="ch" ng-repeat="node in data" data-node="node">' +
couldn't select the li element properly now to see whether it is working
tried,
elm[0].children[0].data()
elm.children[0].data()
etc..
First of all, if it were some third party lib that you are trying to integrate with angular, that might be ok, but now you're generating DOM with angular and embedding data in the DOM. This is very strange.
Second, your test directive template uses ngRepeat, which creates isolate scope and you won't be able to access li items declaratively. You will have to use DOM traversal, which is also not very angular-way-ish.
Third, your view should be bound to model by angulars two-way bindings. Do not try to simulate opposite behaviour on top of that. Either you should not use angular or you should change your approach to your problem, because it will be pain to develop and maintain otherwise.
I would provide a real answer if you could describe what are you trying to achieve and why exactly do you need that model in data. Now the easiest solution would be ditching test directive and rewriting it as such:
controller's template:
<ul>
<li ng-repeat="node in data" model-in-data="node">
<span class="span2">id - {{node.id}}</span>
</li>
</ul>
directive modelInData
.directive('modelInData', function($parse) {
return {
restrict: 'A',
link: function($scope, $element, $attrs) {
var model = $parse($attrs.modelInData)($scope);
$attrs.$set('data', model);
}
}
});
Here each li element adds it's model to the data attribute.