Xrm SDK methods for hiding the header and footer: welcome 🙂
Yesterday I’ve seen the new SDK methods for hiding the header and footer areas on the form, and the first impression was: WOW! I just had the feeling that I’ve missed this feature since ever. So I’ve tried to remember where I’ve needed this in the past. The first that I’ve remembered was showing a form as a dialog. I’ve tried it out, and with this blog I want to share the results.
[Edit] In the meanwhile, I’ve created a new PCF to improve the buttons for this kind of dialogs. Read mode about Dialog Buttons in my next blog post.
The “Big Picture”: The reason for this sdk feature
There might be a lot of other use cases where the new methods are useful, but I’m pretty sure: this SDK methods were not introduced because of these use cases; they are just “side effects”. I suppose it is a part of a bigger change in the direction of converging the app types: model-driven and canvas apps. The first target could be the Custom Pages, where I suppose we’ll be able to integrate also forms. Having the header and footer would look unnatural. The public preview for Custom Pages is scheduled for December 2020, so I guess we’ll find out soon enough.
Who knows, maybe the combination of Forms-Without-Header and Custom-Pages might be the intermediate answer for the deprecation of ClientGlobalContext and parent.Xrm for WebResources that are not on the form. At least until everything will be migrated to PCFs. But that’s a little like “fortune telling”. Who knows what might come in the future.
Let’s imagine that we need a dialog, where we ask a few questions before an action is made. There might be a lot of cases:
- Ask for a reason, an amount and a comment before we deactivate a record
- Ask about a few details before we generate some related records from a ribbon button
- Maybe we don’t use business process flow for an entity, but we have some fields on the form that needs to be confirmed in a special case
Since I need a form for my dialog, I have two possibilities: make a special form for an existing entity, or make a special entity used only for dialog(s) (in my case “orb_dialog”). I think both cases can be used; it depends if I already have the needed attributes on my entity. My Form-Dialog will never save the data. I just use the form for grabbing the input, before I start an action.
To open the form I’ll use Xrm.Navigation.navigateTo. This offers the possibility to open a form in a “modal window”.
The code can be found in my github repository (open.js for this one).
[Edit]: As Andrew Wolfe noticed, the Xrm.Navigation.navigateTo parameter is “createFromEntity” and not “createdFromEntity”.
In my case I had a custom entity which I use only for the dialog: orb_dialog. But as I said, an existing entity could be used too: I just need a dedicated form.
I’ve integrated also a PCF for the the optionset field (my ColorfulOptionset PCF which you can download from pcf-gallery). The possibilities are huge, since I can use every possible form customization.
On click on a button, I want to grab the data introduced, and make an action. For the button I’ve took a PCF from the pcf-gallery: Action Button by Tanguy Touzard. This offers me the possibility to have a PCF, but the script for the action is still registered using form scripting, so I don’t have trouble with PCF restrictions.
[Edit]: In the meanwhile I’ve made a new PCF Control for the button which is translatable, allows the definition of more buttons, and has a few more features. Read more about Dialog Buttons in my next blog post
For the action I’ve took a custom attribute “orb_action” of type text. It’s a dummy attribute, I won’t save it. If the button is hit, the PCF changes it’s value to the one customized for the label (in my case “Evaluate”); so I can register an “OnChanged” to orb_action attribute and start the action.
Form Scripting for the Dialog-Form
[Edit]: The initial idea was to stop the saving, but grab the values. The edited version is much simpler: setting for all attributes the submitMode on “never”. That way the inputs are not relevant for the form, but can grab the input for the Dialog-Action.
I registered the “onChange” for the action attribute (PCF):
In order to have the attribute-list flexible, I have an array with my needed attributes (I don’t take all of them, since there are some more attributes there, which are not visible anymore). My event handler looks like this:
In the “action” event handler “myAction” I do the following:
- grab all the relevant values
- I start the action (in my case the openAlertDialog stands in place for a complex action (it’s enough that it’s a promise)
- I close the form
Form scripting – “X” Button issue
[Edit]: In the initial idea, the “X” button made some issues, because the dialog “Unsaved changes” was showing. This is not relevant anymore, since all the attributes are set on “never submit”, and this “Unsaved changes” doesn’t appear anymore. This part is not relevant anymore, that’s why I’ve set the text to gray.
We cannot control if the “X” button is shown or how the form behaves when it’s clicked. If there is already data introduced in the dialog-form, a confirmation dialog is automatically shown. If the user chooses “Save and continue”, the OnSave is automatically called.
So I had to go through that kind of form scripting we’ve always done, by registering to “onSave” and there stop the saving until we’ve made the async action. ( Unfortunately the last part of the sdk where we cannot work with promises. 😦 )
That’s actually the tricky part of the implementation, even if it’s not much code:
The “dialog name” issue
[Edit]: In the initial idea, the name of the dialog couldn’t be changed, because there were issues with the autosave. The old text is set to gray.
What you see as “New Dialog” on the top of the dialog, is actually the form name. Since I open in “create” mode I get “New”, and since my entity’s name is “Dialog”, I get “New Dialog”.
If you want to set the name of the dialog to something else, just make one record in the “Dialog entity”, and name it exactly how the dialog should be named. In my case “Confirmation”. The difference is that you need to specify the entityId when opening the form:
And now we have a nice title:
This is not possible if you use a “real” entity for the Dialog (in my case it’s an entity only for the dialog). Also this means that you need to transport this entity-data together with the customization. Is it worth to implement it like this? It depends if the customer is ok with “New Dialog” as a title, or not.
I don’t have a good solution for this. I’ve tried to open the form in “Update Mode”. For that I took a record in my “Dialog” Entity, and named it “Confirmation”.
Now the title it’s looking good, but then I had issues with my “onSave” script: the onSave is called before the Confirmation “Unsaved Changes” are triggered, and then I would need another confirmations, while the standard is coming somehow on top. So I’ll go for now with opening the dialog-form in Create mode.
Have a look to the complete code in my github repository.
Dialog as a Wizard?
I think that could work too. For instance we can make more tabs on the form. We use setTabNavigatorVisible(false), which makes the tabs hidden. But using code we can still navigate to the other tabs using “formContext.ui.tabs.get(xxx).setFocus()”. So maybe we need a PCF-Upgrade for “Action Buttons” (or another one, implementing a set of buttons for Wizard-Navigation), and a little more Form-Scripting, but I don’t see why this wouldn’t work.
I’m sure this solution can get more generic and can be better implemented; it’s more like an idea in the beginning. I’m excited about this idea, since it offers all the customizing possibilities, allows us to use even PCFs and form scripting, BusinesRules and we get all the checks on top.
I’m also curious what use cases of this new sdk feature will come in the future.