Getting started with the Custom Control Template in 2020

I’m building my first custom UD Component.

I’ve watched the recording of Adam walk through of the Custom Control Template here and read through the JavaScript Elements doco here

A few observations.
It appears that you need to use Plaster to build the project based on the latest Custom Control Template.
Unlike shown in the walk-through video and the process instructions to build the component you need to run the UD.Build.ps1 script and provide values for the mandatory options. It doesn’t like it if you have renamed the UniversalDashboard.Template.psm1 script.
Using the UD.Build.ps1 and Plaster also looks to require Selenium for the tests associated with building the custom component.

So essentially the process instructions for the Custom Control Template are out dated. I’ve got a few other errors I’m working through associated with the component I’m building, but I’m wondering what else is different, or even if I’m on the right track? Is there an updated process/guide somewhere that I’ve been unable to locate?

Any help, much appreciated.


I’ve removed pester and selenum tests from my modules, as i didn’t quite grasp why build.ps1failed with all the pester stuff in the files.

Now i usually just copy a previous module and control replace it.

I dont think there is a decent up to date guide as of now, but throw this in a enhancement request on github dude :slight_smile:

Welcome to the UD control creators club bro :slight_smile:

1 Like

Hey @darrenjrobinson I got a blog here:- which @BoSen29 helped me out on. More than happy to write a blog on the process I use…? Hopefully reading the blogs I wrote might fill in the bits you are unsure on.

1 Like

thx guys. Looks like I’m on the right track then.

I’ve made a lot of progress and have been able to build a skeleton of a custom module.
I made a bunch of notes along the way to help me next time, but figured it will probably help others too. So here’s the notes.

The following is a step by step guide to building your first UD Custom Control using the UD Custom Control Template without using Plaster in order to understand the files, their relationships and the process. This is especially useful for PowerShell IT Pros that don’t have a dev background and are fumbling their way through their first UD Custom Control. Once you’ve got a handle on the process using Plaster you will understand the values it is requesting and what the outcome from them will be.

  • Get the UD Custom Control Template from Github
    • Extract locally and then copy the 2nd level ud-custom-control-template-master folder to your Projects/Code Directory and rename it to the name of your new Component (e.g UDMyControl) and open the folder in VSCode
    • Rename src\UniversalDashboard.template.psm1 to a name for your Control. e.g UniversalDashboard.UDMyControl.psm1
    • Update src\UniversalDashboard.template.psm1 to remark out Line 15 $AssetId and add in the following two lines as shown below
$AssetId = [UniversalDashboard.Services.AssetService]::Instance.RegisterAsset($IndexJs.FullName)
[UniversalDashboard.Services.AssetService]::Instance.RegisterFramework("Antd", $AssetId)
  • Update src\Components\index.js to change;
	UniversalDashboard.register("<%=$PLASTER_PARAM_ControlTypeName%>", <%=$PLASTER_PARAM_ControlName%>);
	to values based on your Control so that <%=$PLASTER_PARAM_ControlName%> becomes UDMyControl and <%=$PLASTER_PARAM_ControlTypeName%> becomes the name you will use in UD e.g. UD-MyControl


	import UDMyControl from './component';
	UniversalDashboard.register("UD-MyControl", UDMyControl);
  • Update src\Scripts\component.ps1 to replace
function <%=$PLASTER_PARAM_CommandName%>
	=> New-MyControl

	=> becomes UDMyControl
  • Remove the following lines (or remark out)
	            # The keys are case-sensitive in JS. 
	            text = $Text
  • Update src\package.json to change
	<%=$PLASTER_PARAM_ControlName%> => UDMyControl
	"version": "<%=$PLASTER_PARAM_ControlVersion%>" => value becomes the control version e.g 1.0.0
	"description": "<%=$PLASTER_PARAM_ControlDescription%>" => a description for your control 
	"author": "<%=$PLASTER_PARAM_Author%>"   => you
  • Update src\Components\component.jsx to replace the following in the class and export lines
	<%=$PLASTER_PARAM_ControlName%> => UDMyControl

** Update the return text to be something like

	return <h1>My first UD Custom Control works</h1>

** Remove the State section

  • Update src\build.ps1
    ** Insert at Line 15
		New-Item -Path "$BuildFolder\public" -ItemType Directory

** Replace

			<%=$PLASTER_PARAM_ControlName%> => UDMyControl
			<%=$PLASTER_PARAM_ControlDescription%> => a description for your control
			<%=$PLASTER_PARAM_CommandName%> => New-MyControl
			ReleaseNotes = "<%=$PLASTER_PARAM_ReleaseNotes%>" => first release of Universal Dashboard MyControl
			 <%=$PLASTER_PARAM_Author%> => you 
			CompanyName, Copyright etc as required
  • Update src\webpack.config.js
		<%=$PLASTER_PARAM_ControlName%> => UDMyControl
  • Run your first build of your template for your Custom Control
    ** Run .\build.ps1

Success looks like this

And under src\output\UniversalDashboard.UDMyControl you will have your module and the base React lib.

  • Create a Dashboard Script e.g
		import-module UniversalDashboard.Community
		import-module 'C:\<path to your module>\UDMyControl\src\output\UniversalDashboard.UDMyControl\UniversalDashboard.UDMyControl.psm1' -Force 
		Get-UDDashboard | Stop-UDDashboard
		$myDashboard =  New-UDDashboard -Title "My New Custom Control" -Content {    
		Start-UDDashboard -ListenAddress -Port 10006 -Dashboard $myDashboard -Force
  • Access the Dashboard

If you get an error message like the following (Nlog.Extensions.Logging.NLogLogger.Provider… below) when starting the dashboard from VSCode then try running the UD Dashboard script from PowerShell ISE. This worked for me and I think it is to do with my env having multiple versions of dotnet/dotnet core installed and ILoggerFactory is obsolete in .NET Core 3 ( ) ;

You now have a platform to build your custom control.
The rest is up to you in updating your new Custom Control to do whatever it is you are building.

Good luck.


I know this is quite an old post now but just wanted to say thanks @darrenjrobinson for this. I decided to delve into the world of custom components this weekend and this helped me enormously. After running through your example, Adam’s video suddenly made so much more sense to me! It was really helpful to understand how it all hangs together.

On a side note, I noticed what might be a typo in this part:

The control type (I think?) should be UD-MyControl as it needs to match the name provided in index.js

Hey Tom, looking into the last one I wrote, it does appear I make the Function New-MyControl and the type UDMyControl and it was working for the controls I published. Did you get yours working?

Oh sorry I meant the control type name rather than the function name, the one labelled as <%=$PLASTER_PARAM_ControlTypeName%>

It’s referenced in the index.js but in the example one was UDMyControl and the other was UD-MyControl. Just in case someone else followed the example :slight_smile: