Reputation: 1831
I have a situation where I need to manipulate the CSS inside of a controller - I know this is a bit of a no-no but it is necessary in this instance as I will explain below.
I have a title and a description contained inside an list element in an ng-repeat. I want to give the description a CSS class dependent on the height of the title div.
However, when I try to get the height of the 'title' div by id inside the controller, it always just gets the height of the div inside the first element. You can see this explicitly when I get the text of the title. The controller code looks like this:
$scope.getClass = function() {
var title = document.getElementById('title');
var titleHeight = window.getComputedStyle(title, null).getPropertyValue("height");
var titleText = document.getElementById('title').textContent;
if(titleHeight == '50px') {
return 'description-small';
}
else if(titleHeight == '25px') {
return 'description-large';
}
};
The HTML looks like this:
<ul>
<li class="li-element" ng-repeat="item in itemList">
<div id="title" class="title" data-ellipsis data-ng-bind="item.title"></div>
<div class="{{getClass()}}" data-ellipsis data-ng-bind="item.description"></div>
</li>
</ul>
So, dependent on whether the first item in the list has a title over 1 or 2 lines, all subsequent descriptions get the height required for the first item, regardless of how tall/small it's title is.
I assume this is something to do with how ng-repeat works, but I'm pretty new to this and have no idea how to get around it - any ideas?
I've created a plnkr to show the problem here: http://plnkr.co/edit/G1QEq62CbJ0HpNZ0FfSm
REASON FOR MANIPULATING DOM IN CONTROLLER:
I have a title and a description. The title can be 1-2 lines high, depending on the length of the title. If it doesn't fit on 2 lines, I am using the 'data-ellipsis' directive to put ellipsis on the end of the title. Similarly, the description also uses the 'data-ellipsis' for any overflow.
Between the title and the description, they need to have a combined height of 125px, say. But because we don't know how tall the title will be, we don't know how high to set the description. The 'data-ellipsis' directive depends on the value of the height set in the CSS.
So therefore, I need to set the description class dependent on the title height on the fly. If there is another way around this, I'm eager to find out!
Here is a link to the data ellipsis directive: https://github.com/dibari/angular-ellipsis
Upvotes: 3
Views: 6812
Reputation: 9825
The problem is that your assigning the same id to multiple divs. getElementById
is returning the first div with id title
. The solution is simple, add an index to the id. Using ng-attr-id
we can dynamically create ids for every div in the ng-repeat block. The $index
variable gives you the current index of ng-repeat block. Then we pass the $index
to the getClass
function allowing the getClass
to know which title we are talking about.
Plunkr
UPDATES TO YOUR CODE
ng-repeat
<li class="li-element" ng-repeat="item in itemList">
<div ng-attr-id="{{'title'+$index}}" class="title" data-ellipsis data-ng-bind="item.title"></div>
<div class="{{getClass($index)}}" data-ellipsis data-ng-bind="item.description"></div>
</li>
getClass
$scope.getClass = function(i) {
var title = document.getElementById('title'+i);
var titleHeight = window.getComputedStyle(title, null).getPropertyValue("height");
var titleText = title.textContent;
if(titleHeight == '50px') {
console.log("titleheight = 62px");
console.log("titleText = " + titleText);
return 'description-small';
}
else if(titleHeight == '25px') {
console.log("titleheight = 31px");
console.log("titleText = " + titleText);
return 'description-large';
}
};
Upvotes: 3