When working with model-driven applications, we always have to publish our changes to see them applied to the user interface. In some cases, it’s ok. We can keep adding columns to the form and publish those changes one, for example. That’s a little frustrating, but it’s acceptable.
In other cases, this may become much more of a problem. Let’s say there is a javascript web resource which I need to test/fix. If I went about it the regular way, I’d have to do this:
- Update the javascript
- Update corresponding web resource in the application
- Publish my changes
- Refresh the form and see if the fix was successful
- If not, repeat this process until I have desired result
This always feels like a slow-motion movie, to be honest, since it may take a minute to update the script, but it takes a few more minutes to see whether that change was successful because of all the subsequent publishing/refreshing.
Well, there is a faster way to do this, though it all needs to be done slightly differently.
- Event handlers should be attached programmatically in the OnLoad of the form
- The only event handler that should be configured in the form designer is form’s “OnLoad” handler
With that, I could easily use web browser dev tools to add / update my web resources any time I want without having to go through the regular “save->publish->refresh” route. And, once the script is working as expected, I could finally update the web resource.
For example, let’s see how I could use this to add a side pane (see my other post) on form load.
First of all, since onFormLoad will need executionContext parameter, I need mock context to call onFormLoad when I’m doing it outside of the regular execution pipeline:
Also, since I am trying to avoid having to use “publish” every time, in my onFormLoad function I need to make sure that all event handlers are getting attached programmatically. And, also, if I end up calling it more than once, I need to make sure those handlers are not attached multiple time (so, in the example above, I am just removing and re-adding them)
Note: one the script has been tested, I’ll need to update the web resource so all other users could enjoy the benefits of having this script there. I’ll just need to remember not to add mock context and onFormLoad call to the web resource, sine that part will be taken care of by the regular execution pipeline.
Then, of course, I need lookupTaglickHandler in my script, so here is the full version:
function lookupTagClickHandler(executionContext) { var columnName = "parentcustomerid"; var formContext = executionContext.getFormContext(); executionContext._eventArgs._preventDefault = true; var pane = Xrm.App.sidePanes.getPane("LookupDetails"); if(typeof(pane) == "undefined" || pane == null){ Xrm.App.sidePanes.createPane({ title: "Lookup details", paneId: "LookupDetails", canClose: true, width: 500 }).then((pane) => { displayLookupInPane(pane, formContext.getAttribute(columnName).getValue()[0].entityType, formContext.getAttribute(columnName).getValue()[0].id); }); } else{ displayLookupInPane( pane, formContext.getAttribute(columnName).getValue()[0].entityType, formContext.getAttribute(columnName).getValue()[0].id ); } } function displayLookupInPane(pane, entityType, id) { pane.navigate({ pageType: "entityrecord", entityName: entityType, entityId: id }); } function onFormLoad(executionContext) { var columnName = "parentcustomerid"; var formContext = executionContext.getFormContext(); formContext.getControl("parentcustomerid").removeOnLookupTagClick(lookupTagClickHandler); formContext.getControl("parentcustomerid").addOnLookupTagClick(lookupTagClickHandler); } var executionContext = { getFormContext: function(){ return Xrm.Page; } }; onFormLoad(executionContext);
Now all I need to do to test it out (even if there is no web resource at all yet) is open the form in the app, open browser dev tools, and paste my script to the console. Then, if I wanted to make changes to see how they work, I’d just need to update the script and paste it to the dev tools console again. Here, have a look – I’ll open the form, will paste script to the dev tools console, and my side page event handler will start working:
That was fast, wasn’t it?
Now all I need is create a web resource and configure on-load event handler for the form, but I already know that my script is good to go, so I am not anticipating any issues and will only need to go through saving/publishing once.
PS. Another practical application of this approach is that we can test changes locally without “bugging” other team members/users.
Why not simply https://docs.microsoft.com/powerapps/developer/model-driven-apps/streamline-javascript-development-fiddler-autoresponder?
This can be just faster when/if I want to try something, possibly without even making changes to the form/adding a web resource in the first place.