@adam was able to successfully create an element using custom template but the problem is it cannot be used with foreach object in Ud
Error: An Item with the same key has already been added
Can you please provide some code example of what you are trying to do? Also, is that error appearing in the browser or in the log? If you get a log, that would be helpful as well.
component.jsx code
import React from 'react';
import ButtonLoader from 'react_button_loader';
class ReactButtonLoader extends React.Component {
constructor() {
super();
this.state = {
toggleLoader: false
};
}
// state is for keeping control state before or after changes.
handleClick = () => {
if (this.handleClick){
this.setState({toggleLoader: true});
UniversalDashboard.publish('element-event', {
type: "clientEvent",
eventId: this.props.id + "onClick",
eventName: '',
eventData: ''
});
setTimeout(() => {
this.setState({ toggleLoader: false });
}, 2000);
}
};
render() {
return (
<ButtonLoader
isLoading={this.state.toggleLoader}
background="#42b5c1"
loaderType= 'jiggling-lines'
onClick={this.handleClick.bind(this)}
id={this.props.id}
>
{this.props.text}
</ButtonLoader>
);
}
}
export default ReactButtonLoader
index.js code
import ReactButtonLoader from './component';
UniversalDashboard.register("UDButtonLoader", ReactButtonLoader);
script.ps1
<#
.SYNOPSIS
Sample control for UniversalDashboard.
.DESCRIPTION
Sample control function for UniversalDashboard. This function must have an ID and return a hash table.
.PARAMETER Id
An id for the component default value will be generated by new-guid.
.EXAMPLE
PS C:\> <example usage>
Explanation of what the example does
.INPUTS
Inputs (if any)
.OUTPUTS
Output (if any)
.NOTES
General notes
#>
function New-ButtonLoader {
param(
[Parameter()]
[string]$Id = (New-Guid).ToString(),
[Parameter()]
[string]$Text,
[Parameter()]
[string]$isLoading,
[Parameter()]
[string]$background,
[Parameter()]
[object]$onClick,
[Parameter()]
[string]$loaderType
)
if ($null -ne $OnClick) {
if ($OnClick -is [scriptblock]) {
$OnClick = New-UDEndpoint -Endpoint $OnClick -Id ($Id + "onClick")
}
elseif ($OnClick -isnot [UniversalDashboard.Models.Endpoint]) {
throw "OnClick must be a script block or UDEndpoint"
}
}
@{
# The AssetID of the main JS File
assetId = $AssetId
# Tell UD this is a plugin
isPlugin = $true
# This ID must be the same as the one used in the JavaScript to register the control with UD
type = "UDButtonLoader"
# An ID is mandatory
id = $Id
# This is where you can put any other properties. They are passed to the React control's props
# The keys are case-sensitive in JS.
text = $Text
isLoading = $isLoading
background = $background
loaderType = $loaderType
onClick = $onClick
}
}
dashboard:
Get-UDDashboard | Stop-UDDashboard
$Schedule1 = New-UDEndpointSchedule -Every 10 -Second
$init = New-UDEndpointInitialization -Module "C:\Users\test\Downloads\ud-custom-control-template-master\ud-custom-control-template-master\src\output\UniversalDashboard.UDButtonLoader\UniversalDashboard.UDButtonLoader.psd1"
$Services = New-UDEndpoint -Schedule $Schedule1 -Endpoint {
$Cache:Services = (Get-Service -ComputerName "lmspapp001" -Name "*Certification*","*Notification*","*Distribution*") | Select-Object Name,Status | Sort-Object Name | % {
$FontColor = 'Green'
if ($_.Status -ne 'Running') {
$FontColor = 'Red'
}
[PSCustomObject]@{
Name = $_.Name
Status = New-UDElement -Tag 'div' -Attributes @{ style = @{ color = $FontColor } } -Content { $_.Status.ToString() }
Select = if($_.Status -eq 'Stopped'){
New-ButtonLoader -Text "Start" -onClick {
Get-Service -ComputerName "lmspapp001" -Name $_.Name | Start-Service
Show-UDToast -Message "Service Started!" -MessageColor Green -Title $_.Name -Position topCenter -Duration 2500
}
}else{
if($_.Status -eq 'Running'){
New-ButtonLoader -Text "Stop" -onClick {
Get-Service -ComputerName "lmspapp001" -Name $_.Name | Stop-Service
Show-UDToast -Message "Service Stopped!" -MessageColor Red -Title $_.Name -Position topCenter -Duration 2500
}
}
}
}
}
}
$Page1 = New-UDPage -Name "Services" -Icon server -Content {
New-UDElement -Id "Services" -Tag div4 -EndPoint {
New-UDGrid -Id "Grid" -Title "Services" -Headers @("Name","Status","Select") -Properties @("Name","Status","Select") -Endpoint {
$Cache:Services | Out-UDGridData
}
}
New-UDButton -Text "Refresh" -OnClick {
Sync-UDElement -Id "Grid" -Broadcast
}
}
Start-UDDashboard -Endpoint @($Services) -Content{
New-UDDashboard -Pages @($Page1) -Title "Test" -Color '#FF050F7F' -EndpointInitialization $init
} -Port 1000 -Name Test
working example:
Get-UDDashboard | Stop-UDDashboard
Import-Module "C:\Users\test\Downloads\ud-custom-control-template-master\ud-custom-control-template-master\src\output\UniversalDashboard.UDButtonLoader\UniversalDashboard.UDButtonLoader.psd1"
Start-UDDashboard -Dashboard (
New-UDDashboard -Title "Map" -Content {
New-ButtonLoader -Text "test" -onClick {Show-UDToast -Message "test"}
} -EndpointInitialization (New-UDEndpointInitialization -Module ("C:\Users\test\Downloads\ud-custom-control-template-master\ud-custom-control-template-master\src\output\UniversalDashboard.UDButtonLoader\UniversalDashboard.UDButtonLoader.psd1"))
) -Port 1000 -AutoReload
also adam i really appreciate if you can provide an advice on how to turn the spinner off once the onClick completed , i have tried multiple things but could not figure it out so i have used a temp solution in the code above as setTimeout(() => {
this.setState({ toggleLoader: false });
}, 2000);
to turn it off but would be nice to know how to do it once the executed command completed.
thank you
@adam i have noticed that same issue currently the same if you are using New-UDMButton as well,only New-UDButton does not throw this error.
Ok. I am not sure why you are seeing the same key error. I just tried to put UDMuButton in a loop and it seems to work.
Get-UDDashboard | Stop-UDDashboard
$db = New-UDDashboard -Title "Navigation" -Content {
1..10 | % {
New-UDMuButton -Text "Test" -OnClick {
}
}
}
Start-UDDashboard -Dashboard $db -Port 10001
But to your other question, you will want to use the HTTP requests rather than the publish method on the UniversalDashboard object in JavaScript. publish won’t wait until the script is done.
Check out how to call the HTTP reqiest here: https://github.com/ironmansoftware/universal-dashboard/blob/master/src/UniversalDashboard.Materialize/Components/ud-counter.jsx#L24
When that returns, you will get a callback after the script is done and you can set your state.
Thank you adam i figured out the issue, its with the script itself.