InputCanvas appIntermediate

Photo upload

A dashed drop zone that opens the camera or file picker, with a grid of thumbnails, file names and a remove button per photo.

Photo upload in Power Apps Studio
Version
1.0.0
Updated
Verified in Studio
Not yet
Tags
uploadphotoscameraattachments

Overview

A photo upload for inspections and incident reports. A dashed zone in the theme colour invites people to take or choose a photo; on a phone it opens the camera, on a computer the file picker. Each photo appears below as a thumbnail with its file name and a remove button, and the header counts them.

The zone is the classic Add picture control, made transparent and laid over the design, so it accepts one photo at a time. Photos are kept in the collection colFileUploadFiles until you save them, for example to a SharePoint list or Dataverse table with an image column.

When to use

  • Adding photos as evidence to an inspection, finding or request.
  • Up to about ten photos per record.

When not to use

  • Documents such as PDFs: use the attachments control in a form, which handles any file type.
  • Many files at once: let people upload them in SharePoint or OneDrive and link the folder.

Before you paste

  • Something that saves the photos, for example a Save button with ForAll(colFileUploadFiles, Patch(Photos, Defaults(Photos), {Inspection: varInspection.ID, Name: Name, Image: Image})).

Controls used

ControlVersion
GroupContainer1.5.0
ModernText1.0.0
ModernIcon1.1.1
AddMedia2.2.1
Gallery2.15.0
Image2.2.3
ModernButton1.0.0

YAML

Works as is, with example data inline. Paste it into a screen or container; the steps are underHow to paste.

Not yet verified in Power Apps Studio. The control versions are drafted from documentation. If Studio flags one, see How to paste for the fix.

component.yaml
- FileUploadRoot:
    Control: GroupContainer@1.5.0
    Variant: AutoLayout
    Properties:
      BorderColor: =ColorFade(App.Theme.Colors.Darker70, 88%)
      BorderThickness: =1
      DropShadow: =DropShadow.Light
      Fill: =Color.White
      Height: =FileUploadHeader.Height + FileUploadZone.Height + If(FileUploadThumbs.Visible, FileUploadThumbs.Height, FileUploadEmpty.Height) + 2 * 12 + 40
      LayoutDirection: =LayoutDirection.Vertical
      LayoutGap: =12
      PaddingBottom: =20
      PaddingLeft: =20
      PaddingRight: =20
      PaddingTop: =20
      RadiusBottomLeft: =16
      RadiusBottomRight: =16
      RadiusTopLeft: =16
      RadiusTopRight: =16
      Width: =Min(640, Parent.Width)
    Children:
      - FileUploadHeader:
          Control: GroupContainer@1.5.0
          Variant: AutoLayout
          Properties:
            AlignInContainer: =AlignInContainer.Stretch
            DropShadow: =DropShadow.None
            FillPortions: =0
            Height: =26
            LayoutAlignItems: =LayoutAlignItems.Center
            LayoutDirection: =LayoutDirection.Horizontal
            LayoutGap: =8
            LayoutMinHeight: =26
            LayoutMinWidth: =120
          Children:
            - FileUploadTitle:
                Control: ModernText@1.0.0
                Properties:
                  AccessibleLabel: =Self.Text
                  FillPortions: =1
                  FontWeight: =FontWeight.Semibold
                  Height: =26
                  LayoutMinHeight: =0
                  LayoutMinWidth: =80
                  PaddingBottom: =0
                  PaddingLeft: =0
                  PaddingTop: =0
                  Size: =16
                  Text: ="Photos"
                  Wrap: =false
            - FileUploadCount:
                Control: ModernText@1.0.0
                Properties:
                  AccessibleLabel: =Self.Text
                  Align: =Align.Right
                  Color: =ColorFade(App.Theme.Colors.Darker70, 45%)
                  Height: =26
                  LayoutMinHeight: =0
                  LayoutMinWidth: =60
                  PaddingBottom: =0
                  PaddingRight: =0
                  PaddingTop: =0
                  Size: =13
                  Text: =CountRows(colFileUploadFiles) & If(CountRows(colFileUploadFiles) = 1, " photo", " photos")
                  Width: =96
                  Wrap: =false
      - FileUploadZone:
          Control: GroupContainer@1.5.0
          Variant: ManualLayout
          Properties:
            AlignInContainer: =AlignInContainer.Stretch
            DropShadow: =DropShadow.None
            FillPortions: =0
            Height: =128
            LayoutMinHeight: =128
            LayoutMinWidth: =120
          Children:
            - FileUploadFrame:
                Control: ModernText@1.0.0
                Properties:
                  AccessibleLabel: ="Drop zone for photos"
                  BorderColor: =ColorFade(App.Theme.Colors.Primary, 40%)
                  BorderStyle: =BorderStyle.Dashed
                  BorderThickness: =2
                  Fill: =ColorFade(App.Theme.Colors.Lighter80, 50%)
                  Height: =Parent.Height
                  RadiusBottomLeft: =12
                  RadiusBottomRight: =12
                  RadiusTopLeft: =12
                  RadiusTopRight: =12
                  Text: =""
                  Width: =Parent.Width
                  X: =0
                  Y: =0
            - FileUploadIcon:
                Control: ModernIcon@1.1.1
                Properties:
                  AccessibleLabel: ="Add"
                  Fill: =Color.White
                  Height: =40
                  Icon: ="Add"
                  IconColor: =App.Theme.Colors.Primary
                  PaddingBottom: =10
                  PaddingLeft: =10
                  PaddingRight: =10
                  PaddingTop: =10
                  RadiusBottomLeft: =20
                  RadiusBottomRight: =20
                  RadiusTopLeft: =20
                  RadiusTopRight: =20
                  Width: =40
                  X: =(Parent.Width - Self.Width) / 2
                  Y: =18
            - FileUploadPrompt:
                Control: ModernText@1.0.0
                Properties:
                  AccessibleLabel: =Self.Text
                  Align: =Align.Center
                  Color: =App.Theme.Colors.Primary
                  FontWeight: =FontWeight.Semibold
                  Height: =24
                  PaddingBottom: =0
                  PaddingTop: =0
                  Size: =14
                  Text: ="Take or choose a photo"
                  Width: =Parent.Width
                  Wrap: =false
                  X: =0
                  Y: =64
            - FileUploadHint:
                Control: ModernText@1.0.0
                Properties:
                  AccessibleLabel: =Self.Text
                  Align: =Align.Center
                  Color: =ColorFade(App.Theme.Colors.Darker70, 45%)
                  Height: =20
                  PaddingBottom: =0
                  PaddingTop: =0
                  Size: =12
                  Text: ="JPG or PNG, one photo at a time"
                  Width: =Parent.Width
                  Wrap: =false
                  X: =0
                  Y: =88
            - FileUploadPicker:
                Control: AddMedia@2.2.1
                Properties:
                  AccessibleLabel: ="Take or choose a photo"
                  BorderThickness: =0
                  ChangePictureText: =""
                  Color: =Color.Transparent
                  Fill: =Color.Transparent
                  FocusedBorderColor: =App.Theme.Colors.Primary
                  Height: =Parent.Height
                  HoverFill: =ColorFade(App.Theme.Colors.Primary, 94%)
                  OnChange: |
                    =If(
                        Not(IsBlank(Self.Media)),
                        Collect(colFileUploadFiles, {Name: Self.FileName, Image: Self.Media, Added: Now()});
                        Reset(Self)
                    )
                  PressedFill: =ColorFade(App.Theme.Colors.Primary, 88%)
                  Text: =""
                  UseMobileCamera: =true
                  Width: =Parent.Width
                  X: =0
                  Y: =0
      - FileUploadThumbs:
          Control: Gallery@2.15.0
          Variant: Vertical
          Properties:
            AccessibleLabel: ="Added photos"
            AlignInContainer: =AlignInContainer.Stretch
            BorderThickness: =0
            FillPortions: =0
            Height: =RoundUp(Self.AllItemsCount / Max(2, RoundDown(Self.Width / 150, 0)), 0) * Self.TemplateHeight
            Items: =colFileUploadFiles
            LayoutMinHeight: =0
            LayoutMinWidth: =120
            ShowScrollbar: =false
            TabIndex: =0
            TemplatePadding: =0
            TemplateSize: =148
            Visible: =Self.AllItemsCount > 0
            WrapCount: =Max(2, RoundDown(Self.Width / 150, 0))
          Children:
            - FileUploadThumb:
                Control: Image@2.2.3
                Properties:
                  AccessibleLabel: =ThisItem.Name
                  Height: =Parent.TemplateHeight - 36
                  Image: =ThisItem.Image
                  ImagePosition: =ImagePosition.Fill
                  RadiusBottomLeft: =10
                  RadiusBottomRight: =10
                  RadiusTopLeft: =10
                  RadiusTopRight: =10
                  TabIndex: =0
                  Width: =Parent.TemplateWidth - 10
                  X: =0
                  Y: =0
            - FileUploadName:
                Control: ModernText@1.0.0
                Properties:
                  AccessibleLabel: =Self.Text
                  Color: =ColorFade(App.Theme.Colors.Darker70, 30%)
                  Height: =24
                  PaddingBottom: =0
                  PaddingLeft: =0
                  PaddingTop: =0
                  Size: =12
                  Text: =ThisItem.Name
                  Width: =Parent.TemplateWidth - 10
                  Wrap: =false
                  X: =0
                  Y: =Parent.TemplateHeight - 32
            - FileUploadRemove:
                Control: ModernButton@1.0.0
                Properties:
                  AccessibleLabel: ="Remove " & ThisItem.Name
                  Appearance: =ButtonAppearance.Secondary
                  Height: =28
                  Icon: ="Dismiss"
                  Layout: =ButtonLayout.IconOnly
                  OnSelect: =Remove(colFileUploadFiles, ThisItem)
                  RadiusBottomLeft: =14
                  RadiusBottomRight: =14
                  RadiusTopLeft: =14
                  RadiusTopRight: =14
                  Size: =12
                  Tooltip: ="Remove"
                  Width: =28
                  X: =Parent.TemplateWidth - Self.Width - 16
                  Y: =6
      - FileUploadEmpty:
          Control: ModernText@1.0.0
          Properties:
            AccessibleLabel: =Self.Text
            AlignInContainer: =AlignInContainer.Stretch
            Color: =ColorFade(App.Theme.Colors.Darker70, 45%)
            Height: =28
            LayoutMinHeight: =0
            LayoutMinWidth: =80
            PaddingLeft: =0
            Size: =13
            Text: ="No photos yet"
            Visible: =Not(FileUploadThumbs.Visible)
            Wrap: =false

Make it yours

The example runs on sample data. Replace these properties to connect it to your app.

Items on FileUploadThumbs

The photos to show. The picker adds to the collection colFileUploadFiles; sort or filter it here.

In the YAML

YAML
Items: =colFileUploadFiles

Your version

YAML
Items: =Sort(colFileUploadFiles, Added, SortOrder.Descending)

OnChange on FileUploadPicker

What happens with a new photo. Keep the Reset, so the zone is ready for the next one; add a size or count check if you need one.

In the YAML

YAML
OnChange: |
  =If(
      Not(IsBlank(Self.Media)),
      Collect(colFileUploadFiles, {Name: Self.FileName, Image: Self.Media, Added: Now()});
      Reset(Self)
  )

Your version

YAML
OnChange: |
  =If(
      CountRows(colFileUploadFiles) >= 10,
      Notify("You can add up to 10 photos.", NotificationType.Warning),
      Collect(colFileUploadFiles, {Name: Self.FileName, Image: Self.Media, Added: Now()})
  );
  Reset(Self)

How to paste

  1. Open your app in Power Apps Studio.
  2. Check that modern controls are on: Settings → Updates → Modern controls and themes. In newer environments they are on by default.
  3. Copy the YAML with the Copy button above the code.
  4. In the Tree view, select the screen or container that should hold the component and press Ctrl+V. The whole component arrives as one container, FileUploadRoot, with all its controls inside.
  5. Work through Make it yours to swap the example data for your own.

Where your version of Studio has a code view for a control or screen, you can paste the same YAML there instead of into the tree view.

When Studio flags a control version

Each control in the YAML names its version, like Control: ModernButton@1.0.0. If that version is newer than what your environment knows, Studio falls back to the version it has or flags the control. All controls of one type in an app must also use the same version, so an app that already has an older ModernButton can reject the paste. To fix it, insert the same control from the Insert pane, copy it as code, note the version on its Control: line, update every matching line in the YAML and paste again.