Friday, December 31, 2021

PowerApps: Pagination In Gallery

Hello Friends,

Welcome back with another post on PowerApps. Have you ever encountered a scenario where you have hundreds or thousands of records in PowerApps gallery. The most tedious job at that time is to view all records by scrolling. It would be great if we have a pagination kind of functionality similar to other technologies. Unfortunately, PowerApps doesn't provide any pagination concept in Gallery as well as in Data table. Let's try to do with Gallery.

  1. Here, we will first fetch all records from SharePoint List. For this will take help of my earlier article PowerApps: Getting More Than 2000 Items (Using Sequence).
  2. Then we will try to create pagination upon gallery with search feature as well.I had created a list having 4 column with around 25000 items.

  3. Now open the PowerApps maker portal by clicking here.
  4. You may also go to PowerApps maker portal by clicking on Integrate >> PowerApps >> See all apps.
  5. Create a new PowerApps app by clicking "+ Create" >> "Canvas app from blank".
  6. Give in the name. Choose format as Tablet. Click on Create. It will take couple of minutes to create a blank canvas app. The moment, it creates and shows you the blank canvas screen to design, the first most important task you need to do is to Save the app. Click on File >> Save to save the app. The benefit of doing so is that until you save it, your app will remain in browser memory and if anyhow, browser gets closed, your hard work will get vanished. But, if you have saved the app at very beginning, then it gets saved on cloud and PowerApps maker portal start saving the changes every 1-2 minutes automatically.
  7. Let's move on. You will get Screen1 by default. Let's rename it ScreenGalleryPagination by clicking on 3 dots just next to the Screen1 name.
  8. Now we will add a SharePoint connection. For this click on cylinder icon (baiscally it is a database icon). Click on "+ Add data". Search for SharePoint and then click on SharePoint connection.
  9. It will show you the connection with your login. Click on same. Then it will show you the possible sites at right side. Select your SharePoint site. Then it will show you the SharePoint lists. Choose the list and click on Connect.
  10. Now we will fetch the items from this SharePoint list to PowerApps collection. For this click on Apps and then choose "OnStart" property.
  11. Now click on function box and input below code-
  12. ClearCollect(
        Coll_AllItems,
        []
    );
    ClearCollect(
        DataSourceFiltered,
        []
    );
    Set(
        FirstRecord,
        First(TestListSJ)
    );
    Set(
        LastRecord,
        First(
            Sort(
                TestListSJ,
                ID,
                Descending
            )
        )
    );
    Set(
        BatchSize,
        500
    );
    Set(
        MaxIteration,
        RoundUp(
            (LastRecord.ID - FirstRecord.ID) / BatchSize,
            0
        )
    );
    ClearCollect(
        TotalIterations,
        AddColumns(
            AddColumns(
                ForAll(
                    Sequence(MaxIteration),
                    Value
                ),
                "min",
                (FirstRecord.ID + (Value - 1) * BatchSize)
            ),
            "max",
            (FirstRecord.ID + Value * BatchSize)
        )
    );
    ForAll(
        TotalIterations,
        Collect(
            Coll_AllItems,
            Filter(
                TestListSJ,
                ItemID >= min && ItemID < max
            )
        )
    );
    ClearCollect(DataSourceForGalleryItems,Coll_AllItems);
    
  13. Let's explain one by one. Please match with color-
    1. Coll_AllItems: It is a collection to hold all items fetched from SharePoint list.
    2. DataSourceFiltered: It is a collection to hold the result obtained when we click on "Search Record" button.
    3. FirstRecord / LastRecord: These are variables to hold the First item and the Last item of SharePoint list (Sort By ID). 
    4. BatchSize: It is the number of records we will fetch in each call to SharePoint.
    5. MaxIteration: It is the number of total calls we need to made to SharePoint in order to fetch all records.
    6. TotalIterations: It is a collection which is holding the starting ID and the ending ID which will be passed in Filter call to SharePoint. (i.e. 0-500, 501-1000, 1001-1500, ...)
    7. ForAll: It is a function call using which we will fetch all records from SharePoint
    8. ClearCollect: This command we are using to make clone of Coll_AllItems collection. This clone will be used to assign back if we had made a call of Search Record and then we are making call of Search Page / Reload.
  14. With this, we have fetched all records from data source.
  15. Now, click on screen "ScreenGalleryPagination" and add a Gallery (Vertical). Name this gallery as "GalleryListData". Set-
    1. Layout: Title, Subtitle, and body
    2. TemplateSize: 50
    3. Height: Parent.Height-GalleryListData.Y-100
    4. Width: Parent.Width
  16. Title1 label-
    1. Rename it to lblID
    2. X: 0
    3. Y: 0
    4. Width: 100
    5. Height: GalleryListData.TemplateHeight
  17. Subtitle1 label-
    1. Rename it to lblTitle
    2. X: lblID.X+lblID.Width
    3. Y: 0
    4. Width: 400
    5. Height: GalleryListData.TemplateHeight
  18. Body1 label-
    1. Rename it to lblGUID
    2. X: lblTitle.X+lblTitle.Width
    3. Y: 0
    4. Width: 600
    5. Height: GalleryListData.TemplateHeight
  19. I have renamed according to my list columns. You may rename according to your requirements. Other cosmetic surgeries is up to you. 😊
  20. Set GalleryListData >> DataSource to DataSourceForGalleryItems

  21. Now click on Edit link just ahead of Fields property and set the which field is to be displayed in which label.
  22. Now, click on ScreenGalleryPagination and set it's "OnVisible" property. Here we will set 2 variables-
    1. PageSize: It the number of items to be displayed in gallery at a time.
    2. intFilterRecordsFromGallerySource: It is a number which will be used to filter the number of such items from entire collection using FirstN so that we can then use LastN with PageSize to get the actual items to be displayed on screen when user will click on Next/Previous icon.
  23. The code is-
  24. UpdateContext({PageSize: 0});
    UpdateContext({intFilterRecordsFromGallerySource: 0});
    UpdateContext(
        {
            PageSize: RoundDown(
                GalleryListData.Height / GalleryListData.TemplateHeight,
                0
            )
        }
    );
    UpdateContext({intFilterRecordsFromGallerySource: PageSize});
    
  25. Now, click on GalleryListData gallery and choose Items property and assign the below code.
  26. LastN(
        FirstN(
            DataSourceForGalleryItems,
            intFilterRecordsFromGallerySource
        ),
        If(
            Mod(
                intFilterRecordsFromGallerySource,
                PageSize
            ) = 0,
            PageSize,
            Mod(
                intFilterRecordsFromGallerySource,
                PageSize
            )
        )
    )
  27. This code is what we were talking about in above step. The moment you add this code, you may find that the gallery becomes blank. This is due to non initialization of variable. So, save the app and play it once.
  28. With this, we have completed the basic display part. Now the actual work starts where we will implement the pagination and will see, how it works.
  29. Let's add a reload button at top. For this, add a Reload icon at top and update it's "OnSelect" property as-
    1. ClearCollect(DataSourceForGalleryItems,Coll_AllItems);
      
  30. The other changes are-
    1. Rename it to IconReload
    2. Height: 40
    3. Width: 40
    4. Padding Left/Right/Top/Bottom: 5
    5. Color: RGBA(255, 255, 255, 1)
    6. Fill: RGBA(50, 86, 160, 1)
    7. Y: 0
    8. X: 1326 (or set it accordingly to make it extreme right)
  31. Now, we will add Previous / Next button. For this, add Left icon and update it's "OnSelect" property as-
    1. If(
          intFilterRecordsFromGallerySource < 2 * PageSize,
          UpdateContext({intFilterRecordsFromGallerySource: PageSize}),
          UpdateContext(
              {
                  intFilterRecordsFromGallerySource: intFilterRecordsFromGallerySource - If(
                      intFilterRecordsFromGallerySource = CountRows(Coll_AllItems),
                      If(
                          Mod(
                              CountRows(Coll_AllItems),
                              PageSize
                          ) = 0,
                          PageSize,
                          Mod(
                              CountRows(Coll_AllItems),
                              PageSize
                          )
                      ),
                      PageSize
                  )
              }
          )
      
      ); 
  32. The other changes are-
    1. Rename it to IconPrevious
    2. Height: 40
    3. Width: 80
    4. Padding Left/Right/Top/Bottom: 5
    5. Color: RGBA(255, 255, 255, 1)
    6. Fill: RGBA(50, 86, 160, 1)
    7. Y: GalleryListData.Y+GalleryListData.Height
    8. X: 0
  33. Now, add right icon and update it's "OnSelect" property as-
    1. UpdateContext(
          {
              intFilterRecordsFromGallerySource: intFilterRecordsFromGallerySource + If(
                  intFilterRecordsFromGallerySource + PageSize <= CountRows(Coll_AllItems),
                  PageSize,
                  If(
                      intFilterRecordsFromGallerySource = CountRows(Coll_AllItems),
                      0,
                      Mod(
                          CountRows(Coll_AllItems),
                          PageSize
                      )
                  )
              )
          }
      
  34. The other changes are-
    1. Rename it to IconRight
    2. Height: 40
    3. Width: 80
    4. Padding Left/Right/Top/Bottom: 5
    5. Color: RGBA(255, 255, 255, 1)
    6. Fill: RGBA(50, 86, 160, 1)
    7. Y: GalleryListData.Y+GalleryListData.Height
    8. X: Parent.Width-IconRight.Width
  35. Another section has been completed. Now save the app and play it. Click on Next / Previous buttons. The gallery is getting loaded accordingly.
  36. Now, we will try to show the 
    1. Page Number / Total Pages
    2. Total Records
    3. First Page
    4. Last Page
    5. Search By Page Number
    6. Search By Record Title
  37. Let's add Page Number / Total Pages. For this, add a label.
    1. Rename it to lblCurrentPage
    2. Width: 75
    3. Height: 40
    4. X: 0
    5. Y: Parent.Height-lblCurrentPage.Height
    6. BorderThickness: 1
    7. Text: RoundUp(intFilterRecordsFromGallerySource/PageSize,0)
    8. Align: Center
  38. Add another label.
    1. Rename it to lblSeparatorSignLabel
    2. Width: 30
    3. Height: 40
    4. X: lblCurrentPage.X+lblCurrentPage.Width
    5. Y: Parent.Height-lblSeparatorSignLabel.Height
    6. BorderThickness: 1
    7. Text: /
    8. Align: Center

  39. Add another label.
    1. Rename it to lblTotalPages
    2. Width: 80
    3. Height: 40
    4. X: lblSeparatorSignLabel.X+lblSeparatorSignLabel.Width
    5. Y: Parent.Height-lblTotalPages.Height
    6. BorderThickness: 1
    7. Text: RoundUp(CountRows(DataSourceForGalleryItems)/PageSize,0)
    8. Align: Center

  40. This way Page Number / Total Pages is done.
  41. Now we will Total Number of Records.
  42. Add a label.
    1. Rename it to lblTotalRecordsText
    2. Width: 130
    3. Height: 40
    4. X: lblTotalPages.X+lblTotalPages.Width+20
    5. Y: Parent.Height-lblTotalRecordsText.Height
    6. Italic: true
    7. Text: Total Records:

  43. Add another label.
    1. Rename it to lblTotalRecordsValue
    2. Width: 75
    3. Height: 40
    4. X: lblTotalRecordsText.X+lblTotalRecordsText.Width
    5. Y: Parent.Height-lblTotalRecordsValue.Height
    6. Text: CountRows(DataSourceForGalleryItems)

  44. This way, Total Records display gets done.
  45. Now we will work upon First Page & Last Page. Let's Add Last Page button.
  46. Add a button-
    1. Rename it to btnLastPage
    2. Width: 125
    3. Height: 40
    4. X: Parent.Width-btnLastPage.Width
    5. Y: Parent.Height-btnLastPage.Height
    6. Text: Last Page
    7. OnSelect: UpdateContext({intFilterRecordsFromGallerySource:CountRows(DataSourceForGalleryItems)});

  47. Add another button-
    1. Rename it to btnFirstPage
    2. Width: 125
    3. Height: 40
    4. X: Parent.Width-btnLastPage.Width-btnFirstPage.Width-20
    5. Y: Parent.Height-btnLFirstPage.Height
    6. Text: First Page
    7. OnSelect: UpdateContext({intFilterRecordsFromGallerySource:PageSize});
  48. This way First Page & Last Page also done.
  49. Now, we will implement Search Page / Search Record functionality. For this-
  50. Add a button-
    1. Rename it to btnSearchPage
    2. Width: 150
    3. Height: 40
    4. X: lblTotalRecordsValue.X+lblTotalRecordsValue.Width+20
    5. Y: Parent.Height-btnSearchPage.Height
    6. Text: Search Page
    7. OnSelect: 
      1. If(
            Value(txtSearchBox.Text) <= RoundUp(
                CountRows(DataSourceForGalleryItems) / PageSize,
                0
            ),
            UpdateContext({intFilterRecordsFromGallerySource: Value(txtSearchBox.Text) * PageSize})
        )
        
  51. The moment, you add the OnSelect code, it will error because, till now, we haven't added textbox, from which it will pick the data. So don't worry,, we are going to add it next.
  52. Add a textbox (Text input).
    1. Rename it to txtSearchBox
    2. Default: "" (Blank)
    3. Width: 250
    4. Height: 40
    5. X: btnSearchPage.X+btnSearchPage.Width+20
    6. Y: Parent.Height-txtSearchBox.Height
  53. Add another button
    1. Rename it to btnSearchRecord
    2. Width: 150
    3. Height: 40
    4. X: txtSearchBox.X+txtSearchBox.Width+20
    5. Y: Parent.Height-btnSearchRecord.Height
    6. Text: Search Record
    7. OnSelect: 
      1. ClearCollect(
            DataSourceFiltered,
            Search(
                Coll_AllItems,
                txtSearchBox.Text,
                "Title"
            )
        );
        ClearCollect(
            DataSourceForGalleryItems,
            DataSourceFiltered
        );
        UpdateContext({intFilterRecordsFromGallerySource: PageSize});
        

  54. This way, we have completed our functionality. Below are the screenshots.
  55. Home Screen-
  56. Next Button-
  57. Previous Button-
  58. Search Page-
  59. Search Record-
  60. Reload-
  61. Last Page-
  62. First Page-
  63. This way you can implement pagination.
  64. You may also implement numeric pagination. For this, you need to visit my next post. PowerApps: Pagination In Gallery (Implement Numeric Pagination).
With this, I am concluding this post.
Happy Coding !!!
Will see you again with some new topics.

Stay Safe !
Stay Healthy !


Bye... Bye... 2021
Wishing All Readers & Coders . . .        !!! A Very Happy New Year !!!

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.