Using a custom function to create components in a PUD

Hi,

I was wondering if a custom function could be used to create various PUD elements and if so, are there are recommended practices.

For example, let’s say I’m creating a grid that has a UDButton, UDCheckBox a UDIcon and some blurb of text.

Right now in my script, my code has defined in the -endpoint {} section. It’s a lot of code to get what I want. Lots of if statements, lots of things that could potentially be reused.

What I would love to do, is instead of something like this:

Foreach ($RowToCreate in $AllRowObjects)
{
New-udbutton
New-udcheckbox
new-udicon
other elements, blah blah blah
}

What I would like to do is something like what’s below. And instead the “invoke-customfunction” would do all the work i’m currently doing in-line in my foreach loop.

Foreach ($RowToCreate in $AllRowObjects)
{
invoke-customfunction
}

Is this possible with all the various run spaces and what not? Right now a lot of what I do is $Session:Var based. Is there a special way I need to call the function or execute things insside the function?

Hi @ericcsinger,

Your function should work fine, as long as you keep the -id’s unique.

$session:var is avaliable to everything, just don’t try to use this in scheduled-endpoints.

In a foreach loop, everything will run in a single runspace, so no need to worry about that :slight_smile:

Shout if you require any more guidance!

Ok, so you’re saying in my custom function i just need to create a unique ID.

Example:

Function Invoke-Custom
{
New-UDButton -id “Unique”
Some other commands
}
Foreach ($Object in $Session:All_Objects)
{
Invoke-Custom $object
}

Will this ALL stay in a given in my $Session scope, or would the lack of me specifying the $Session:Object (foreach) and the lack of me capturing the invoke-custom results in a $Session var (inside the loop) cause stuff to get lost or pushed into the global scope?

I was reading up on native PS scopes and PS functions run in their own scope by default.

Right now, I’m pretty much putting anything that has a $ in the $Session scope.

Hey @ericcsinger not too sure if you are over-complicating things? You cool to explain what you want to achieve from this if it’s not too top secret…I am super-behind on writing blogs on UD but I got a blog here:- https://psdevuk.github.io/ud-flix/Serving-SQL-on-a-UniversalDashboard/
of using SQL, but wondering if you are importing the custom function prior to starting the dashboard? Or nesting this in an endpoint? https://psdevuk.github.io/ud-flix/Content-vs-Endpoint/
I think you mentioned you using 2.9.0 I am not using that version, but I have found that on one of my personal dashboards I had issues sticking to many variables in the SESSION variable.
I also like to output my variables to text files just so I know the correct data is in that variable.
I hope this helps

basically, I’m creating a portal for manager to login to and manage thier contractors, temps and vendors. They’ll be able to do things like disable accounts, extend expiration dates, etc.

The reason i’m using the $session variable is I’m assuming from a security perspective that’s the best way to attack this. I’m also presuming that if i want to avoid conflicts, that’s the only way to ensure each manager only sees and interacts with objects they’re entitled to.

It’s totally possible I’m overthinking this as this is my first attempt at using universal dashboard. I’m just trying to avoid any potential security risks.

My company is a bit behind on technology, but I am using certain Active Directory security groups which then allows me to control which menu items certain users have access to, it also allows me to decide who and who cannot access the universal dashboard. So I do not how secure you want it, but I find that seems good enough security for me.
I don’t see why if you are using endpoints why you cannot just use a plain variable to hold the data, as variables in endpoints should be able to be read by other endpoints. -Broadcast is the variable parameter you want to stay away from as that broadcasts it across all dashboards running. I had an issue with modals popping up on other peoples screens (bug related) as if it was broadcasting results. I built a dashboard a good while ago located here:- https://github.com/psDevUK/universal-dashboard this might give you some ideas on a design perspective…? I assume you are using the professional version yeah? This dashboard links to an SQL database I put together to help manage the vehicles in the company…totally un-IT I know, but instead of using about 15 different spreadsheets to update I gave them a dashboard instead which rights to SQL.
Also if your new to UD there is a marketplace here:- https://marketplace.universaldashboard.io/
which holds lots of components which may not exist in UD already…this may also help you in designing or populating components with the data you want. I hope all this rambling will lead you to the answer you are looking for…always happy to ramble some more if you need some more direction :slight_smile:

In my case, there is going to be a dynamic page called “Managers Portal”

Each manager will hit the same page, and use the same variables in scripting. My concern was that if i use a variable called $Managers_Staff (as an example). That if Manager A and Manager B are logged in at the same time, they’d overwrite each others variables. Is this not the case?

Example:

new-udpage -endpoint {
$Manager = Get-aduser $User
$Managers_Staff = Get-AdUser -filter ‘Manager -eq $Manager.DN’
New-UDGrid -Content {
$Managers_Staff | out-griddata
}
}

that’s a really quick, potentially wrong syntax example of something I might do. My concern in this example as that if ManagerA and ManagerB hit the same dynamic page, that the variables would get overwritten. Is that a wrong assumption?

ok so if you have a login to the dashboard, then you should be able to use the $user variable which is referencing the current user. As far as I know each endpoint runs in its own runspace…so you should be good…I have never had a user raise a purchase order or complaint and have it over-written on the respective dashboards I have running for these.

Hey, so now that i’m not using the $session scope, i’m seeing that my elements are missing. For example, i’m creating a checkbox, but when i click on the check, checkboxid is empty.

This is inside a foreach loop. The $ADObject. is the object being looped.

$CheckboxStateID = $null
$CheckboxID = $null
CheckboxStateID = "CheckBoxStateID_($ADObject.SamAccountName)"
CheckboxID = "CheckBoxID_($ADObject.SamAccountName)"
#This section creats a check box for the user
Checkbox_Element = New-UDElement -Id ($CheckboxStateID) -Tag “span” -ErrorAction Stop
Checkbox = New-UDCheckbox -Id ($CheckboxID) -ErrorAction Stop -OnChange {
#This is where it bombs out, the checkbox ID is empty.
Checkbox_Element_Temp = Get-UDElement -Id (CheckboxID) -ErrorAction Stop set-UDElement -Id ($CheckboxStateID) -Content {Checkbox_Element_Temp.Attributes["checked"]} -ErrorAction Stop Sync-UDElement -Id ($CheckboxStateID) -ErrorAction Stop

I’m pulling what little hair I have out :smiley:

Essentially, I want to run the page its self in a singular run space, but as far as needs go, I don’t need anything else to be seperated out. Should I be putting $Global:VarName?

I basically want to make sure each user that launches a page has their own private admin page.

Ultimately it renders a grid, and that part DOES work. It’s when I click on the checkbox inside the grid.

Just a friendly bump.

I think you need to show people the whole picture, instead of snippets of script bits here and there post your whole dashboard to give everyone a better understanding. There is tons of info on this site which may or may not have the answer you need. So you mention clicking the checkbox inside the grid…so I assume you looked at Out-UDGridData with selectable rows? to see how another user has achieved this? Like I said dude, be more helpful if you posted your dashboard here or on github least let people have a better understanding of what does not work. Peace

I can / will after checking out the linked page. My dashboard in totality is probably a 1k lines of code, maybe more. So if it comes to that, I’ll see if i consolidate it down to a simple example.

I had a similar example linked working when I was using a $Session scope for everything. And that’s what’s part of the struggle. I’m more than confident it’s realated to runspaces, but there just doesn’t seem to be good documentation on how to design a dashboard with runs spaces being taken into account.

I’ve seen a lot of Adams documentation, but I think the problem is he’s writing from an experts view and not a newbie. Essentially a lot of assumption of knowledge. That’s not me saying there are no good examples out there. There are. But it’s not enough, and there really needs to be a 101 / 102 course on setting up a dashboard, with some real world examples. Also, in the main documentaiton section, the command and all it’s parameters should be in one place. Right now i have to bounce between github and the main PUD docs page.

Even something as simple as why would i use a -content param vs. -endpoint isn’t in any documnetiaton that’ i’ve found.

I’m paying for PUD just FTR, so i’m not using the community edition. If I was using the community only version I wouldn’t inheritently expect this.

Only asked to post the dashboard, as I am not sure I 100% understand your exact issue…as far as run spaces you can look at these with the plugin in VSCODE, as far as I understand each runspace is created from an endpoint…and unless you give your stuff -Id parameter it autonames the runspaces…as for content vs endpoint I did my own blog here:-


But this was just based off of documentation on UD and personal experiance. So I hope this helps.
As for your other concerns on documenting and runspaces @adam can you advise please and thank you :slight_smile:

Thanks, that helps with the content vs. endpoint.

Lemme give the other example a try. I think they are doing what i was getting ready to try next anyway.

BTW, is it safe to assume content does NOT run in a seperate runspace then?

@psDevUK - Thanks for the signal boost and helping out so much.

@ericcsinger - Please let me know if Adam’s blog answers your questions. If not, let’s circle back on exactly what you’re trying to accomplish. There’s a lot of discussion in this thread and I want to make sure we solve it the right away.

1 Like

Hey @ericcsinger as far as I know the content is just static, so does not use a run space. Once it’s loaded what is inside the content block it’s done.

Thanks, i’m going to give the example linked a shot and I’ll report back.

1 Like

I think i got it now.

So… in my checkbox, inside the -OnChange Parameter I needed to create a new endpoint as part of the “on check” and pass a parameter.

Like documented above.

1 Like