Zombie tabs

At least two places in our system we experience zombie tabs, tabs that after an error message are impossible to close.

I can now reproduce the issue: We have a custom "Delivery Risks" tab on parts. If I add a new risk and open it, the UI thinks the object is in a dirty state. Just opening it and closing it again, I get a popup with "Changes have not been saved. What do you want to do?". If I select "save" here, I get the error 

"The Command for the Command Alias 'SaveItem' failed."
and the form still thinks the object has unsaved changes. However, if I click "Discard", I get the following error in the web console:
Uncaught (in promise) CUIError: The Command for the Command Alias 'UnlockItem' failed.
at T0 (factory.ts:152:8)
at Object.execute (factory.ts:169:24)
at onUnlockCommand (include.aspx?classes=tearoffWindow:915:36)
at async eval (eval at x0 (factory.ts:53:9), <anonymous>:30:10)
at async T0 (factory.ts:140:10)
and I now have a zombie tab which is impossible to close.

I can avoid creating a zombie tab by clicking "Edit" and "Save" manually in the form. Even though there are no changes, that apparently syncs the state properly.

Requesting the object with AML studio, newly created items in potential zombie state look exactly like ones which have been edited and saved, so the problem isn't in the database end. Fully logging out and logging in again also clears potential zombie state, but merely closing the Part does not. So it's some kind of Item cache in the frontend which thinks the Risk object is dirty - or possibly it's the Form Item which is dirty.
I suspect it has something to do with how I save the item. It's saved in a slightly unusual way, in a popup form. But before I dig into explaining how, does any of this sound familiar to you? Perhaps someone with better understanding of how the front end caching in Aras works can immediately tell me what's wrong here.

This is Aras 31 by the way. 
  • Some more digging and debugging later, I add the following in an onLoad action on the offending form:

    console.log("Am I dirty? " + aras.isDirtyEx(document.item));
    console.log("Dirty according to direct check? " + ArasModules.item.isDirty(document.itemType, document.itemID));
    console.log("Am I in an edit state? " + aras.isEditStateEx(document.item));
    console.log("Edit state according to direct check " + ArasModules.item.isEditState(document.itemType, document.itemID));
    On an object which has been manually saved and thus isn't at risk of turning into a zombie tab, I get this:
    Am I dirty? false
    Dirty according to direct check? false
    Am I in an edit state? false
    Edit state according to direct check false
    However, on a buggy item, I get this:
    Am I dirty? true
    Dirty according to direct check? false
    Am I in an edit state? true
    Edit state according to direct check false
    How is this possible? If the edit state is false according to ArasModules.item.isEditstate, then aras.isDirtyEx should always be false as well! It checks for that and returns early, since (reasonably enough!) things that aren't in an edit state shouldn't be able to be dirty.
  • Hi Harald,

    I am familiar with the error and confirm that it can happen due to dirty items. For example the use case described in this post can super easily create dirty items by editing a part outside regular change control:  RE: non-revisioned properties or xProperties on an item 

    But as far as I understand you just have regular relationship. 

    Some question:

    - Does the same error appear on other similar relationship tabs (like Part BOM, or Part Costs)?
    - Do you use a regular relationship or NULL relationship?
    - Do you use additional JS Methods like Form "onLoad" or RelationsihpType "onInsertRow" that update a property automatically?

  • I am not 100% sure where else in the system it appears. The custom Delivery Risk ItemType is a null relationship.

    I found out the reason for the most confusing item logging above: when I properly use the ItemTypeID instead of document.itemType in the ArasModules.item calls above, it at least gave me consistent result with the isDirtyEx / isEditStateEx methods on the aras object.

    I create the new Delivery Risk item in one method, and pass it to a modal dialog where the user can fill out the details and hit save. When they hit save, it then just .apply()-s the item I passed in. That is enough to create the item, but apparently not to make the frontend believe that it was created. My attempts to tell it in that function have all failed, however, I have worked around it by adding an onLoad function on the view/edit form, which checks if the item is dirty and saves it if it is. I still would very much like to know the right way to do it/prevent dirty objects from being created in the first place.

  • It makes sense that the behavior appears in the context of a dialog. This is very similar to the post I mentioned before. 

    In the shown use case dirty items aren´t a big problem as the dialog is mainly executed from released items. In my case I reset the "isDirty" attribute to 0 inside the dialog callback function. This is important when user close the dialog without doing anything. Things get more complicated for item that can still be edited.

    Quote: "checks if the item is dirty and saves it if it is" 

    That´s one approach that I also use sometimes! You can even execute the save action automatically in silent mode to avoid to distract the user. As alternative, you can of course just tell the user to save first by themselves. This is an actual code sample that I use when I don´t want use the silent mode. Use case is an automatically sort_order renumbering function that user can use while working with the relationships:

    // Don´t renumber if item is dirty (=unsaved changes)
    const isDirty = window.aras.isDirtyEx(contextItem.node);
    if (isDirty)
    {
      return aras.AlertError("Blablabla please save first....");
    }

    I am not sure if this is the official recommended way to deal with dirty items. But I have seen similar solutions in the OOTB Innovator code.