Skip to content

Instantly share code, notes, and snippets.

@sancarn
Last active May 7, 2025 09:11
Show Gist options
  • Save sancarn/d629782e9681ef98b35b9cb713958b09 to your computer and use it in GitHub Desktop.
Save sancarn/d629782e9681ef98b35b9cb713958b09 to your computer and use it in GitHub Desktop.
A buggy gallery input control for PowerApps.

So I'm not really sure how to work around this issue...

  1. I set NewItemTemplate to my custom schema e.g. {PowerRating: "", Image: ""}
  2. I try to set my RenderItem to {Icon: "", Title: "Pump " & Record.Index, Description: "Power: " & Record.PowerRating}

But I get the error here that PowerRating isn't a member of the Record?!.

I think PowerApps is re-using the Record as defined in NewItemTemplate at component build time, but this basically just removes the whole point of using a component... I don't have to have to change my component every time I want to use it? What on earth is that about?!

PowerAppsGenericTypeBug

New Template Item example

Render Item Type Error

Any thoughts?

ComponentDefinitions:
GalleryInput:
DefinitionType: CanvasComponent
CustomProperties:
Default:
PropertyKind: Input
DisplayName: Default
Description: The default value in the property
RaiseOnReset: true
DataType: Table
Default: =
DeleteItem:
PropertyKind: Action
DisplayName: DeleteItem
Description: Delete item by its index
ReturnType: None
Parameters:
- Index:
Description: Index of the item to delete
DataType: Number
Default: =100
Description:
PropertyKind: Input
DisplayName: Description
Description: The description to display below the question title
DataType: Text
Default: ="My description goes here"
NewItemTemplate:
PropertyKind: Input
DisplayName: NewItemTemplate
Description: When new items are added to the gallery they will use this data structure.
DataType: Record
Default: =
OnEdit:
PropertyKind: Event
DisplayName: OnEdit
Description: Called when an item in the gallery is selected
ReturnType: None
Default: =
Parameters:
- Record:
Description: The selected record in the gallery
DataType: Record
Default: |-
=Patch(Self.NewItemTemplate, {Index: 1})
RenderItem:
PropertyKind: InputFunction
DisplayName: RenderItem
Description: A custom property
DataType: Record
Default: |-
={Icon: "", Title: "", Description:""}
Parameters:
- Record:
Description: The record to extract the name from
DataType: Record
Default: |-
=Patch(First(_items), {Index: 1})
- Index:
Description: The index of the item to be displayed
IsOptional: true
DataType: Number
Default: =100
Title:
PropertyKind: Input
DisplayName: Title
Description: The title / question to ask
DataType: Text
Default: ="My Title"
TotalHeight:
PropertyKind: Output
DisplayName: TotalHeight
Description: A custom property
DataType: Number
UpdateItem:
PropertyKind: Action
DisplayName: UpdateItem
Description: Updates an item by it's index
ReturnType: None
Parameters:
- Index:
Description: Index of item to update
DataType: Number
Default: =100
- UpdateData:
Description: Data to update item with
DataType: Record
Default: =Self.NewItemTemplate
Validation:
PropertyKind: InputFunction
DisplayName: Validation
Description: 'A function which can be called to check if the value added is valid. The function should return a table of errors of the form {type: "Error"|"Warn", text: "My error here"}'
DataType: Table
Default: |-
=Table([{Type: "", Text: ""}])
Parameters:
- Value:
Description: The value inputted by the user.
DataType: Table
Default: =_items
Value:
PropertyKind: Output
DisplayName: Value
Description: The value inputted by the user
DataType: Table
isDescriptionHTML:
PropertyKind: Input
DisplayName: isDescriptionHTML
Description: If true, the description will render as HTML. If false it will render as text.
DataType: Boolean
Default: =true
isValid:
PropertyKind: Output
DisplayName: isValid
Description: Whether the input meets the validation criteria
DataType: Boolean
Properties:
DeleteItem: |-
=With(
{ tgt : Index( _items, Index + 1 ) }, // 1-based helper
Remove( _items, tgt );
/* re-number the remaining rows so indices stay contiguous */
ForAll(
Filter( _items, Index > Index ),
Patch( ThisRecord, { Index: Index - 1 } )
)
);
Height: =700
OnReset: |-
=ClearCollect(_items, ForAll(Sequence(CountRows(Self.Default)), Patch(Index(Self.Default, Value), {Index: Value+1}))); //Replace with default set of items
TotalHeight: =GalleryInput_Errors.Y + GalleryInput_Errors.AllItemsCount * GalleryInput_Errors.TemplateHeight
UpdateItem: |-
=/* UpdateItem(Index:number, UpdateData:Record) behaviour inside the component */
With(
{
tgt : Last( FirstN( _items, Index+1 ) ) // 0-based → +1
},
Patch( _items, tgt, UpdateData )
);
Value: =_items
isValid: =CountRows(GalleryInput.Validation(_items))=0
Children:
- GalleryInput_Container:
Control: [email protected]
Variant: AutoLayout
Properties:
Height: =GalleryInput.Height
LayoutDirection: =LayoutDirection.Vertical
Width: =GalleryInput.Width
Children:
- GalleryInput_HorizCont:
Control: [email protected]
Variant: AutoLayout
Properties:
FillPortions: =0
Height: =160
LayoutDirection: =LayoutDirection.Horizontal
Children:
- GalleryInput_DescCont:
Control: [email protected]
Variant: AutoLayout
Properties:
FillPortions: =0
Height: =100
LayoutDirection: =LayoutDirection.Vertical
LayoutJustifyContent: =LayoutJustifyContent.Center
LayoutMinHeight: =60
Width: =GalleryInput_HorizCont.Width-GalleryInput_AddCont.Width
Children:
- GalleryInput_Title:
Control: [email protected]
Properties:
AutoHeight: =true
BorderColor: =RGBA(0, 18, 107, 1)
Font: =Font.'Open Sans'
FontWeight: =FontWeight.Bold
Text: =GalleryInput.Title
Width: =GalleryInput_Container.Width
X: =40
Y: =40
- GalleryInput_Description:
Control: [email protected]
Properties:
AutoHeight: =true
Font: =Font.'Open Sans'
HtmlText: =Substitute(If(GalleryInput.isDescriptionHTML, "$root", "<p>$root</p>"), "$root", GalleryInput.Description)
Size: =14
Width: =GalleryInput_DescCont.Width
X: =5
Y: =70
- GalleryInput_AddCont:
Control: [email protected]
Variant: AutoLayout
Properties:
FillPortions: =0
LayoutDirection: =LayoutDirection.Vertical
LayoutJustifyContent: =LayoutJustifyContent.Center
Width: =150
Children:
- GalleryInput_AddBtn:
Control: Classic/[email protected]
Properties:
AlignInContainer: =AlignInContainer.Center
BorderColor: =RGBA(0, 18, 107, 1)
Color: =RGBA(0, 18, 107, 1)
Height: =GalleryInput_AddCont.Height
Icon: =Icon.Add
OnSelect: |-
=Collect(
_items,
Patch( // tag it with an Index if you keep one
GalleryInput.NewItemTemplate,
{ Index: CountRows(_items) + 1 } // 1-based
)
);
PressedFill: =RGBA(240,240,255,1)
Width: =GalleryInput_AddCont.Width
- GalleryMain:
Control: [email protected]
Variant: BrowseLayout_Vertical_TwoTextOneImageVariant_ver5.0
Properties:
BorderColor: =RGBA(0, 18, 107, 1)
FillPortions: =0
Height: =GalleryMain.TemplateHeight*GalleryMain.AllItemsCount
Items: =_items
OnSelect: =GalleryInput.OnEdit(ThisItem)
TemplateSize: =100
Children:
- Separator1:
Control: [email protected]
Properties:
BorderColor: =RGBA(0, 18, 107, 1)
Fill: =RGBA(0, 18, 107, 1)
Height: =1
OnSelect: =Select(Parent)
Width: =Parent.TemplateWidth
Y: =Parent.TemplateHeight - Self.Height
- GalleryItemEditBtn:
Control: Classic/[email protected]
Properties:
BorderColor: =RGBA(0, 18, 107, 1)
Color: =RGBA(0, 18, 107, 1)
Height: =GalleryMain.TemplateHeight
Icon: =Icon.NextArrow
OnSelect: =Select(Parent)
Width: =GalleryMain.Width - (GalleryItemImage.X+GalleryItemImage.Width)
X: =GalleryItemImage.X+GalleryItemImage.Width
- GalleryItemImage:
Control: [email protected]
Properties:
BorderColor: =RGBA(0, 18, 107, 1)
Height: =GalleryMain.TemplateHeight
Image: =If(GalleryInput.RenderItem(ThisItem,ThisItem.Index).Icon<>"",GalleryInput.RenderItem(ThisItem,ThisItem.Index).Icon,SampleImage)
OnSelect: =Select(Parent)
Width: =150
X: =GalleryItemName.X+GalleryItemName.Width
- GalleryItemDesc:
Control: [email protected]
Properties:
BorderColor: =RGBA(0, 18, 107, 1)
Font: =Font.'Open Sans'
Height: =GalleryMain.TemplateHeight*2/3
OnSelect: =Select(Parent)
Size: =14
Text: =GalleryInput.RenderItem(ThisItem,ThisItem.Index).Description
VerticalAlign: =VerticalAlign.Top
Width: =GalleryItemName.Width
X: =GalleryItemName.X
Y: =GalleryMain.TemplateHeight/3
- GalleryItemName:
Control: [email protected]
Properties:
BorderColor: =RGBA(0, 18, 107, 1)
Font: =Font.'Open Sans'
FontWeight: =FontWeight.Bold
Height: =GalleryMain.TemplateHeight/3
OnSelect: =Select(Parent)
Size: =14
Text: =GalleryInput.RenderItem(ThisItem,ThisItem.Index).Title
Underline: =true
Width: =400
X: =GalleryItemIndex.X + GalleryItemIndex.Width
- GalleryItemIndex:
Control: [email protected]
Properties:
BorderColor: =RGBA(0, 18, 107, 1)
Color: =RGBA(166, 166, 166, 1)
Font: =Font.'Open Sans'
Height: =GalleryMain.TemplateHeight
OnSelect: =Select(Parent)
Text: =ThisItem.Index
Width: =30
- GalleryInput_Errors:
Control: [email protected]
Variant: BrowseLayout_Vertical_TwoTextOneImageVariant_ver5.0
Properties:
BorderColor: =RGBA(0, 18, 107, 1)
Height: =150
Items: =GalleryInput.Validation(GalleryMain.AllItems)
LayoutMinHeight: =0
TemplateSize: =23
Children:
- GalleryInput_Errors_Icon:
Control: Classic/[email protected]
Properties:
BorderColor: =RGBA(0, 18, 107, 1)
Color: =If(ThisItem.Type="Warn",RGBA(150,150,0,1), RGBA(255,0,0,1))
Height: =23
Icon: =If(ThisItem.Type="Warn",Icon.Warning, Icon.Error)
OnSelect: =Select(Parent)
Width: =26
- GalleryInput_Errors_Text:
Control: [email protected]
Properties:
BorderColor: =RGBA(0, 18, 107, 1)
Color: =If(ThisItem.Type="Warn",RGBA(150,150,0,1), RGBA(255,0,0,1))
Font: =Font.'Open Sans'
Height: =23
Size: =10
Text: =ThisItem.Text
Width: =620
X: =20
- GalleryInput_Errors_Seperator:
Control: [email protected]
Properties:
BorderColor: =RGBA(0, 18, 107, 1)
Fill: =RGBA(0, 18, 107, 1)
Height: |+
=1
OnSelect: =Select(Parent)
Width: =Parent.TemplateWidth
Y: =23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment