NJW
NJW

Reputation: 73

ValueHelpDialog error adding element with duplicate id

The first time I open die ValueHelpDialog and chose an item there are no errors. However when I open the dialog again and click on the same entry I get the following error:

Uncaught Error: Error: adding element with duplicate id 'EQ5IPAKCZJMZR' at constructor.x.registerElement (Core-dbg.js:2711)...

When I click again i get another error:

Uncaught TypeError: Cannot read property 'getKey' of undefined at constructor.onVHOK (ValueHelper.js?eval:35)...

When I click a third time it works without an error.

I use

this._dialog.close();
this._dialog.destroy();

in the event handlers for the ok event as well as for the cancel event.

Is the second error related to the first one? I thought closing and destroying the dialog would be enough to avoid those duplicate id errors.

Edit: More code Controller:

this._ValueHelper = new ValueHelper();

/* Calling valueHelper */
onVH: function(oEvent) {
            this._ValueHelper.handleValueHelp(this, {
                srcCtrl: oEvent.getSource()
            });
        },

ValueHelper.js:

handleValueHelp: function(oController, mOptions) {
            if (mOptions == null) {
                mOptions = {};
            }

            this._controller = oController;
            this._view = oController.getView();
            this._model = this._controller.getModel();
            this._callback = mOptions.fnCallback;
            this._srcCtrl = mOptions.srcCtrl;
            if (this._dialog != null) {
                this._dialog.open();
            } else {
                this._buildValueHelp();
            }
        },

_buildValueHelp: function() {
            var oDialog = sap.ui.xmlfragment(
                "xxx.view.fragments.valueHelper.ValueHelp",
                this
            );
            this._view.addDependent(oDialog);
            this._dialog = oDialog;

            this._registerEnterEvent(oDialog);
            var oTable = sap.ui.xmlfragment(
                "xxx.view.fragments.valueHelper.ValueHelpTable",
                this
            );
            this._table = oTable;
            oDialog.setTable(oTable);
            oDialog.open();
        },

onVHOK: function(oEvent) {
            var sId = oEvent.getParameter("tokens")[0].getKey();

            this._handleOk(sId);

            this._dialog.close();
            /*this._dialog.destroy();*/
        },

onVHClose: function() {
            this._dialog.close();
            /*this._dialog.destroy();*/
        },

ValueHelp.fragment:

<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:vh="sap.ui.comp.valuehelpdialog" xmlns:fb="sap.ui.comp.filterbar">
    <vh:ValueHelpDialog  key="id" ok="onVHOK" cancel="onVHClose" selectionChange="onVHSelectionChange"
        title="Car" supportMultiselect="false" supportRanges="false" supportRangesOnly="false" descriptionKey="Car">
        <vh:filterBar>
            <fb:FilterBar advancedMode="true" filterBarExpanded="true" search="onVHShipSearch">
                <fb:filterGroupItems>
                    <fb:FilterGroupItem groupName="car" name="n1" label="Name">
                        <fb:control>
                            <Input  />
                        </fb:control>
                    </fb:FilterGroupItem>
                    <fb:FilterGroupItem groupName="car" name="n2" label="imnr">
                        <fb:control>
                            <Input/>
                        </fb:control>
                    </fb:FilterGroupItem>
                </fb:filterGroupItems>
            </fb:FilterBar>
        </vh:filterBar>
    </vh:ValueHelpDialog>
</core:FragmentDefinition>

ValueHelpTable.fragment:

<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:t="sap.ui.table">
    <t:Table rows="{path: '/Cars'}"  selectionBehavior="Row" selectionMode="Single">
        <t:columns>
            <t:Column>
                <t:label>
                    <Label text="Number"/>
                </t:label>
                <t:template>
                    <Text text="{ path: 'number', formatter: '.formatter.leadingZeroes' }"/>
                </t:template>
            </t:Column>         
            <t:Column>
                <t:label>
                    <Label text="Name"/>
                </t:label>
                <t:template>
                    <Text text="{name}"/>
                </t:template>
            </t:Column>
            <t:Column>
                <t:label>
                    <Label text="imnr"/>
                </t:label>
                <t:template>
                    <Text text="{imnr}"/>
                </t:template>
            </t:Column>
        </t:columns>
    </t:Table>
</core:FragmentDefinition>

Upvotes: 1

Views: 3412

Answers (2)

Boghyon Hoffmann
Boghyon Hoffmann

Reputation: 18064

I thought closing and destroying the dialog would be enough to avoid those duplicate id errors.

Usually, it is. But the dialog is probably still being referenced by other elements. In this case, you could...:

  • Try to remove the references from all reference holders before destroying it.
    For example, if the view has the dialog in its <dependents> aggregation:

    this._dialog.attachEventOnce("afterClose", () => {
      this.getView().removeDependent(this._dialog);
      this._dialog.destroy();
      this._dialog = null;
    }).close();
    

    But I'm not aware of any effective ways to find all reference holders. Hence ..

  • Double check if it's really necessary to destroy the dialog every time after closing. Such an attempt is usually a sign of premature optimization. As long as there is no memory issue, I'd keep the dialog in memory so that it can be opened quickly next time.

If you're destroying the dialog for another reason, please add it to your question.

Upvotes: 1

I had the same problem and resolved it by making this sequence of choices.

    closeIndicator: function(oEvent) {
        this._dialog.close();  // First: close fragment
        this._dialog.destroy();  //Second: destoy fragment 
        this._dialog=null;  // Third: null name/pointer 
    },

The problem is that when you perform the destroy you do not nullify the variable.

Upvotes: 0

Related Questions