Search code examples
svgsapui5graphic

OpenUI5 after closing dialog fragment controls disappear


I´m pretty new to UI5 and I don´t understand why my controls disappear. But let me explain the problem step-by-step

I have created a view, a corresponding controller and a custom graphic control using D3. The troubling part of the view looks like that:

<Page ...>
    <!-- some FlexBoxes here... -->
    <html:div style="clear:both; overflow-x:hidden; overflow-y:hidden; height: 94%;" class="sapUiNoMargin">
        <html:div id="graphs" style="background-color:white; border: 1px solid lightgray; height:89%; width:100%;" >
            <core:HTML id="htmlCanvasWrapper" content="&lt;svg id='htmlCanvas' height='65%'&gt;&lt;/svg&gt;"></core:HTML>
            <core:HTML id="htmlCanvas2Wrapper" content="&lt;svg id='htmlCanvas2' height='23%'&gt;&lt;/svg&gt;"></core:HTML>
            <core:HTML id="htmlCanvas3Wrapper" content="&lt;svg id='htmlCanvas3' height='12%'&gt;&lt;/svg&gt;"></core:HTML>
        </html:div>
       <!-- the closing elements follow here... -->

If someone wonders what I try to do above: the svg-elements are holding my graphics and the surrounding 'core:HTML' element is used for showing/hiding the charts via jquery (not everyone is allowed to see everything. In addition the 3 graphics should use the full remaining space on the page (the graphics are scaling) that is not used by the filter (FlexBoxes above), by the header and the footer.

Until now everything works as expected. That means the graphics are drawn and everything looks alright so far. Now I want to show a legend for the graphics (which color means what and so on). That I have accomplished by showing a dialog from a fragment

Dialog definition:

<core:FragmentDefinition xmlns="sap.m" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:l="sap.ui.layout" xmlns:core="sap.ui.core">
    <Dialog title="{i18n>VollePfanneLegende.Title}">
        <html:style>
        <!-- style definitions for the legend -->
    </html:style>
    <l:VerticalLayout>
        <l:content>
            <FlexBox>
                <html:div class="icon" style="background-color: #68ACE9; border-color: #68ACE9; border-radius: 50%;"/>
                <html:div class="hspacer"/>
                <Text text="{i18n>VollePfanneLegende.IstTemp}"/>
            </FlexBox>

            <html:div class="vspacer"/>

            <FlexBox>
                <html:div class="icon" style="background-color: #F70206; border-color: #F70206; border-radius: 50%;"/>
                <html:div class="hspacer"/>
                <Text text="{i18n>VollePfanneLegende.SollTemp}"/>
            </FlexBox>
    <!-- ... -->

In the footer is a button to show the dialog (fragment) which also works as it should (the graphics are still shown in the background), BUT: when I close the dialog the dialogs are only visible for some fractions of a second and then they disappear! When select the now empty space with the debugger it shows that the div with the id "graphs" is empty!

<div id="__xmlview1--graphs" style="border: 1px solid lightgray; border-image: none; width: 100%; height: 89%; background-color: white;"></div>

But now I find a new div AFTER the content div that holds my graphics

<div class="sapUiHidden sapUiForcedHidden" id="sap-ui-preserve" aria-hidden="true" style="width: 0px; height: 0px; overflow: hidden;">
    <svg id="htmlCanvas" height="65%" data-sap-ui-preserve="__xmlview1--htmlCanvasWrapper>...</svg>
    <svg id="htmlCanvas2" height="23%" data-sap-ui-preserve="__xmlview1--htmlCanvas2Wrapper>...</svg>
    <svg id="htmlCanvas3" height="12%" data-sap-ui-preserve="__xmlview1--htmlCanvas3Wrapper>...</svg>
</div>

EDIT1: Code for opening/closing the dialog fragment. The "onShowLegend" function shows the dialog, the "legendClose" function is called when you click the close button on the dialog.

onShowLegend: function() {
    if (! this._oLegendDialog) {
        this._oLegendDialog = sap.ui.xmlfragment("portal.view.vollePfanneLegende", this);
    }

    // toggle compact style
    this.getView().addDependent(this._oLegendDialog);
    jQuery.sap.syncStyleClass("sapUiSizeCompact", this.getView(), this._oLegendDialog);
    this._oLegendDialog.open();
},

legendClose: function() {
    if (this._oLegendDialog) {
        this._oLegendDialog.destroy();
    }
    this._oLegendDialog=null;
}

I don´t have a clue how to prevent UI5 to hide my graphics. Please help. Thanks in advance

EDIT 2: if I wrap the "core:HTML" elements e.g. in a VerticalLayout the graphics are not removed after closing the dialog. BUT: The height of VerticalLayout can´t be set. I need something that uses the full height of the unused page, because the graphics are scaling depending on their parent control height.

<html:div id="graphs" style="background-color:white; border: 1px solid lightgray; height:89%; width:100%;" >
    <l:VerticalLayout width="100%">
        <l:content>
            <core:HTML id="htmlCanvasWrapper" content="&lt;svg id='htmlCanvas' height='65%'&gt;&lt;/svg&gt;"></core:HTML>
            <core:HTML id="htmlCanvas2Wrapper" content="&lt;svg id='htmlCanvas2' height='23%'&gt;&lt;/svg&gt;"></core:HTML>
            <core:HTML id="htmlCanvas3Wrapper" content="&lt;svg id='htmlCanvas3' height='12%'&gt;&lt;/svg&gt;"></core:HTML>
       </l:content>
   </l:VerticalLayout>
</html:div>

Best regards Jochen


Solution

  • After some hours of trial and error and a lot of Internet surfing I have come up with the following code that does exactly what I want

    <html:div style="clear:both; overflow-x:hidden; overflow-y:hidden; height: 94%;" class="sapUiNoMargin">
        <html:style>
            .graphs {
                    background-color:white; 
                    border: 1px solid lightgray; 
                    width:100%;
                    height: calc(100% - 85px); /* Height of RangeSlider area */
            }
            .sapMScrollContScroll {
                 height: 100%;
            }
        </html:style>
        <html:div id="graphs" class="graphs">
            <ScrollContainer width="100%" height="100%" focusable="false" horizontal="false">
                <core:HTML id="htmlCanvasWrapper" content="&lt;svg id='htmlCanvas' height='65%'&gt;&lt;/svg&gt;"></core:HTML>
                <core:HTML id="htmlCanvas2Wrapper" content="&lt;svg id='htmlCanvas2' height='23%'&gt;&lt;/svg&gt;"></core:HTML>
                <core:HTML id="htmlCanvas3Wrapper" content="&lt;svg id='htmlCanvas3' height='12%'&gt;&lt;/svg&gt;"></core:HTML>
            </ScrollContainer>
        </html:div>
    
        <!-- Rest of the view here... -->
    </html:div>
    

    As I understand the solution the wrapping in a UI5 container makes sure that the redraw event after closing the dialog has a control that can handle it.