Up until now, none of my PCF controls were meant to be readonly. But, of course, it would only make sense to prevent updates for inactive records and/or when some of those controls are set to be readonly in the form designer:
Dynamics Ninja has already described the basics in his earlier post: https://dynamicsninja.blog/2019/11/25/is-your-pcf-control-read-only/
Just to reiterate, though, we can use the property below to decide whether our PCF control should be readonly or not:
context.mode.isControlDisabled
However, depending on how that PCF control is implemented, making it readonly might end up being a bit more involved exercise.
For both N:N treeview and N:N dropdown controls in my PCF controls solution, I ended up using the following approach (and, it seems, it may work for other controls, too):
- There would be a transparent overlay div element
- That div element would only become visible once isControlDisabled has been set to true
From the HTML/CSS standpoint, for this to work I would actually need 3 elements:
- A container div (which could be the container element provided by the PCF framework)
- An overlay div added as a very first child element to the container above
- Main PCF component element
For those 3, I’d be using the following CSS styles:
.pcf_container_element { position:relative; width:100%; height:100%; overflow:none } .pcf_overlay_element { width:100%; height:100%; border:0px; background-color:transparent; z-index:10; position:absolute; top:0; left:0 } .pcf_main_element { position:relative; top:0; left:0 }
With these settings, my overlay element would be placed just on top of the main element, so there would be no way to click/change anything in the control. And, yet, since my overlay element would have transparent background, it would no be visible to the user. Which means this would all result in a read-only PCF component presented to the user.
You can take a closer look at the code in the github repository, but here is the summary:
setReadonly function will change visibility of the overlay element depending on what’s stored in the isControlDisabled property
public setReadonly(): void
{
(<HTMLElement>this.container.firstElementChild).style.display = this.contextObj.mode.isControlDisabled == false ? "none" : "block";
}
</HTMLElement>
In the “init” method of the PCF
control, all those elements will be created with correct styles
container.classList.add("pcf_container_element"); this.overlayDiv = document.createElement("div"); this.overlayDiv.classList.add("pcf_overlay_element"); container.appendChild(this.overlayDiv); this.mainContainer = document.createElement("select"); this.mainContainer.id = this._ctrlId; .. this.mainContainer.classList.add("pcf_main_element");
Those 3 css styles will be added to the PCF control through an additional css resource file
Finally, setReadonly function should be called from somewhere
It should definitely be called from the updateView; however(and maybe that’s something I need to look into a bit more), I found that for my N:N treeview control updateView does not get called on the initial load, for example. Therefore, I’m also calling it once the treeview has been initialized.
That seems to be all there is to it. And, of course, those css styles above can be tweaked a little more. For example, you might want to add background color to the overlay element. In that case it might make sense to use rgba colors to make the background transparent.