1

I have the problem that I had some divs with ng-show, they should present some screens, that work separately well. Inside those screens there is some javascript code that depends of the height to display. Without that value all the library does not work well (similar to have a width auto and no height so the width cannot be calculated and does not display).

The problem is that those divs have not height because at that point they are hidden by ng-show=false. And for some reason until the display is not complete the height remains with 0. But the code executes before it gets shown.

I used a delay in order that everything works fine.

But is there another better way to solve this problem without a time delay?

perseus
  • 1,322
  • 1
  • 16
  • 22

3 Answers3

4

When you set ng-show you conditionally add the class .ng-hide to your element, which applies the CSS rule display: none;. When elements have a display of none, JavaScript will always report the height and width of those elements as 0.

It seems to me that if you want to hide an element whilst the page loads, then perhaps you should look at using ng-class in combination with visibility: hidden, such as is suggested in this answer. An "invisible" element will continue to consume the space it normally would in the DOM and so you'll be able to calculate it's dimensions accurately.

Community
  • 1
  • 1
Ian Clark
  • 9,237
  • 4
  • 32
  • 49
  • Also, if you want the element to keep his height but do not want it to keep occupying its space in the DOM (which `visibility: hidden` does), you could also add a `position: absolute` on it – floribon Apr 27 '15 at 18:12
  • Sometimes that'll be useful (maybe with viewport units?), but if you take the element out of it's normal flow it'll lose it's containing width ([See Fiddle](http://jsfiddle.net/t0y93v58/)). – Ian Clark Apr 27 '15 at 18:16
  • You are right, that would only work with an element that has an explicit width/height. – floribon Apr 27 '15 at 18:26
  • Yes, that was the problem it is like angular does not remove .ng-hide immediately. So with the delay it waited until that class was removed. The solution was to remove immediately the .ng-hide class with removeClass and then execute the code normally and worked fine. Thanks – perseus Apr 27 '15 at 19:49
  • No problem, if this answer solved your issue perhaps you could consider marking it as resolved :) – Ian Clark Apr 27 '15 at 20:02
1

ng-show: false applies, by default, a display: none to your element, which will prevent you of getting the height and width of the element.

Instead of using a delay, I think that a better approach is to change the styles that are applied, by overwritting the .ng-hide:not(.ng-hide-animate) styles.

As mentioned in other answers, you could go with visibility: hidden and position absolut, however, what really worked for me, was the example provided by Angular itself, in its official documentation (under the Overriding .ng-hide section):

.ng-hide:not(.ng-hide-animate) {
    display: block!important;
    position: absolute;
    top: -9999px;
    left: -9999px;
}
0

Using delay is definitely not the right answer. My working solution is the following. (i am using angular components, which i recommend).

<div ng-click="showChild = !showChild">
 .......
</div>
<div ng-show="showChild">
  <child-component showChild ="showChild" ></child-component>
</div>

As you can see, i am passing the status of the child as a parameter to the child-component. In the controller of the child, i am using $onChange, a function which is triggered when the variable (showChild) is changed

   self.$onChanges = function (changesObj) {
      if('information' in changesObj) {
          if(changesObj['showChild']['currentValue']) {
            var width = document.getElementById("location").offsetWidth;
            // this is the actual width
          }
        };
      };

No matter if you are using or not angular components, the logic is the same. You should watch the variable that shows or hide the <div> and onChange (if the variable is true), calculate the width