USD: How to handle Save & Close without getting a confirmation dialog

In our implementation of the Unified Service Desk, we show each entity in its own separate hosted control and thus, a separate tab. Everything worked perfectly, except that every time we pressed Save & Close, we would get a dialog asking for confirmation before closing the tab. Very annoying, and something that needed to be fixed. After a lot of investigation and considering different approaches, what I will show here is how we finally dealt with the issue.

For our solution we’re taking care of saving the entity through code, and handling the tab close through the USD, which is equivalent to clicking on the tab’s “X”.

JavaScript code used for managing tab closure

The code to handle this should be located in a common JavaScript repository, so that it’s available to all entities. This is all the code needed, so there’s no need to create any new code every time you want to add the functionality to a new service request.

// Execute Save & Close from custom ribbon button, for USD compatibility.
function USDSaveAndClose (context) {
    // Remove and add event to save.
    Xrm.Page.data.entity.removeOnSave(SSFCU.FireUSDSaveAndCloseEvent);
    Xrm.Page.data.entity.addOnSave(SSFCU.FireUSDSaveAndCloseEvent);
    // Save the current entity.
    Xrm.Page.data.entity.save();
}

This first function removes and attaches a function to the OnSave CRM event. Removing and attaching it makes sure that it’s only there once, and avoids repeated execution. There might be a more elegant way to achieve this, but this works and has no performance impact. Note that the function being attached is the next one we’ll take a look at.

The last thing this function does is to save the entity. Note that we’re doing a regular save, and not using the saveandclose parameter.

function FireUSDSaveAndCloseEvent () {
    window.open('http://event/?eventname=SaveAndClose');
}

The second function, which is the one fires at the end of the save process, fires a USD Hosted Control event. This is a cool way of pushing events via code into the USD, and works as long as you have an event defined for the current active Hosted Control.

Notice that the event we’re firing, SaveAndClose, is not a standard event. We’ll be creating this event later.

Creating the new command bar button and command

To create the new command bar button, we used the fantastic Ribbon Workbench. If you don’t have it, get it now! Click here to download it from the awesome people at Develop 1.

Create a solution that includes the entities you will be modifying, and don’t forget to include the web resource that contains the code shown above. Now, run the Ribbon Workbench, load your solution, and select the entity your wish to modify. Select the Command Bar at the top right click in the Commands tree node to add a new command.

1

Now give the command a significant name, something like “publisher.entity.function.Command” works nicely:

2

Click the lookup button in actions, and add a new JavaScript function. It will have two parameters: the function name (must match the name of the first function shown above), and the web resource it comes from, for which you’ll get a lookup. The end result would be something like this:

4

Now it’s time to create our own Save & Close button! From the Toolbar area, drag a button to the spot where you want it. We placed ours between the default Save and Save & Close buttons. You’ll need to copy a couple of lines from the existing Save & Close button. I’ve enclosed screenshots comparing between the default button and my new one.

Default button

Default button

New Save & Close button

New Save & Close button

As shown here, I copied the image source paths, and the labels (mostly). In our case, we also need to add the Command that will be run, and it will be selected from the dropdown in the Behaviour section. In this screenshot, it shows in the CommandCore are too because I’ve already saved this record.

Now, hide the old Save & Close button by right-clicking on it and selecting the option from the context menu. Your command bar should look like this:

7

After you’re done, click the Publish button to make the changes effective.

Adding the custom event and action call

Go to CRM and create a new event for your hosted control, and name it SaveAndCloseThis is the custom event we’ll be firing, and will take care of closing our tab after saving, avoiding any confirmation dialogs from the IE process.

 8

Create a new Action Call for this event, and name it however fits your standards. Reference the standard UII Action Close, which will close the current active tab for this hosted control. It should look like this:

9

Remember to add these two to the appropriate configurations! That’s all we need! Fire up the USD and test it out. Let me know if you have any questions.

Have fun!

Advertisements
Tagged , , , ,

6 thoughts on “USD: How to handle Save & Close without getting a confirmation dialog

  1. Mike says:

    Hi!
    Thanks for great blog, found tons of interesting guides for USD configuration.
    Regarding the confirmation dialog on save. I have an opposite problem: USD does not pop up a confirmation dialog (I have auto-save on, so in case there’s form validation errors/warnings it should pop up a dialog warning that the form you’re leaving is not saved) and just closes the tab, so user just loses data without even knowing that. I couldn’t find any settings regarding this behavior. Would really appreciate if you could give me any clues on that.

    Liked by 1 person

    • josekercado says:

      Thank you for stopping by! I’m glad I can help a bit. About the issue you’re facing, I assume you’re closing the tab using the “X”? The issue here is that clicking that is totally “external” to the CRM page you’re on, if you get what I mean — the hosted control is in a way totally agnostic of what’s being shown in it, so when you close the tab it really doesn’t care and closes it immediately.

      You could create an action call with the SetUserCanClose UII action, and as data you put in “UserCanClose=false” (without the quotes). Then, tie that to the PageLoadComplete event. That would eliminate the “X” in the tab.

      Then create your own Close button which in reality would to a Save & Close as shown here, and you should be able to take care of that.

      Let me know if that works. Thanks!

      Like

      • Mike says:

        Hi! Thanks for quick reply. It took me a while to set everything up, but now I ended up with the following approach, maybe someone will find it useful:

        What we needed was when the user Closes case session, the Case in CRM should be automatically saved (not just closed with losing all changes as it is by default) but if there are some required fields missing or validation errors it should warn the user and allow him to decide if he wants to fix them or close anyway (same way that closing a crm form tab works in web browser).

        – We removed the “X” on the tab as you proposed.
        – We use sessions and the idea is that when the user closes session (click on “X” on session tab) there is an event to hook into in the Session Tabs hosted control, it’s called “SessionCloseRequested”. So in we added a RunScript action to that event to call a custom JavaScript function on CRM form. It is important that this action call is first.
        – The function then saves the form using client side sdk and calls a custom event in USD hosted control. If the validation or save fails the script would pop up a confirmation to ask user if he wants to close and loose unsaved changes. If yes it calls the same custom event in USD hosted control.
        – The USD custom Event on our CRM Page hosted control then calls “Close” on itself and “CloseSession” action on Session Tabs hosted control.
        – Now the “SessionCloseRequested” is executed second time but this time the actual CRM form is already saved and closed so we can close the session without fears. Which is done by simply configuring all other action calls (we kept the standard calls that save notes, timers and calls “CloseSession” action in order to finish closing it) with a condition that they should only execute if the actual CRM control is already closed. Since this control starts the session it will always be opened until it is closed by our custom Action. The check looks like “[[CaseControl.HostedControlStatus]+]” = “closed”

        Hope that my description is more or less understandable. The whole implementation looks quite complex but I didn’t find an easier way to implement that.

        Like

      • josekercado says:

        That’s a nice solution, Mike! I can’t think of another way to get what you wanted. I’m glad I could be of some help!

        Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: