Search code examples
javascripthtmldialogpolymerweb-component

Get clientHeight of content inside custom web-component nested in Polymer paper-dialog


I''ll try to explain my problem the clearest I can.

I'm using <paper-dialog> and <paper-dialog-scrollable>.

In <paper-dialog-scrollable> I have a form which is a custom web-component.

In this form I use an other custom web-component which expands and collapses content.

The default state of the content is collapsed.

In the expandcomponent I save the clientHeight of the content in a variable contentHeight and set the height of the content to 0.

I have a function toggle() which is executed when a trigger is clicked.

toggle() sets the contents height to contentHeight.

Now this works perfectly when I use my form or the expand component alone, but it doesn't work when they're nested inside a paper-dialog because the clientHeight is then 0.

Code:

<paper-dialog with-backdrop style="min-width: 90%;">
   <paper-dialog-scrollable>
      <my-custom-form-component></my-custom-form-component>
   </paper-dialog-scrollable>
</paper-dialog>

Code from <my-custom-form-component> :

<div id="custom-expand-component-trigger"></div>
<custom-expand-component trigger="custom-expand-component-trigger">
   blabla a lot of content......
</custom-expand-component>

toggle() function (inside <custom-expand-component>):

function toggle(){
  if(!that.opened){
    content.style.height = contentHeight + 'px';  //contentHeight is 0 when form is nested in <paper-dialog>
  } else{
    content.style.height = startHeight;
  }
  that.opened = !that.opened;
}

Any Ideas how I can get the clientHeight even if my form is inside the dialog?

I hope this is clear enough.

Help would be greatly appreciated


Solution

  • The clientHeight of an hidden element is 0 so you cannot get it until it is rendered.

    The element is actually rendered first when the <paper-dialog> is opened. When it happens, the iron-overlay-opened event is fired. That's an opportunity to get the right clientHeight if you haven't set it before:

    myDialog.addEventListener( "iron-overlay-opened", function ()
    {
        this.querySelector( "custom-expand-component" ).init()
    } )
    

    Inside the init() method, set the correct values for your private variables:

    var CEC = Object.create( HTMLElement.prototype )
    CEC.createdCallback = function () {
        var that = this
        var startHeight
        var contentHeight 
    
        this.init = function () {
            if ( !contentHeight ) {
                contentHeight = this.clientHeight + "px"  //OK
                startHeight = this.getAttribute( "start-height" )
                opened = false                  
                this.style.height = startHeight
            }
        }
    
        document.getElementById( this.getAttribute( "trigger" ) ).onclick = toggle
    
        function toggle() {
            opened = !opened
            that.style.height = ( opened )? contentHeight : startHeight
        }
    }
    document.registerElement( "custom-expand-component", { prototype: CEC } )
    

    The CSS transition is working now:

    custom-expand-component {
        display: block ;
        overflow-y: scroll ;
        transition: height 0.5s ;
    }