cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
sperry1625
Solution Supplier
Solution Supplier

Variables and Data Structures in Canvas Apps

I have a query for everyone.  I am building another Canvas App and I have a lot of data I need to keep track of while navigating through the various screens. I really do not want to have 100's of global variables or collections (all global as well), they become hard to keep track of and manage. Microsoft doesn't give proper tools for managing them either, which makes it more difficult. Here are my thoughts:

FYI: I use data structures like the below as this is a mobile app and I use SaveData()/LoadData() in the app and want to keep structures simple and straight-forward.

I try and use Data Structures, so I define a variable like this:

Set(
    gblMyData,
    {
        Dirty: false,
        Loaded: Now(),
        Details: Table( Defaults( 'tbl_WidgetDetail' ),
        LineItems: Table( Defaults( 'tbl_WidgetOrders' ),
        Photos: Table( Defaults( 'tbl_WidgetPhotos' ) )
    }
);
// Or
UpdateContext(
    {
        gblMyData:
        {
            Dirty: false,
            Loaded: Now(),
            Details: Table( Defaults( 'tbl_WidgetDetail' ),
            LineItems: Table( Defaults( 'tbl_WidgetOrders' ),
            Photos: Table( Defaults( 'tbl_WidgetPhotos' ) )
        }
    }
);

This allows my to group related data together and use and leverage it together.  The problem with this is Microsoft provides no way to easily update these types of data structures. If I only want to update the Dirty flag, I can't. I would need to turn this into a single row Collection by using ClearCollect() instead of Set() and UpdateContext(), and add an Id column to the definition. Then I can use UpdateIf() but I still have an issue with setting the 3 table items.

Scenario

I need to populate the LineItems column with the contents from a SQL Server table. I use something like the following:

UpdateIf(
    gblMyData,
    Id = 1,    // Added Id column so I can use UpdateIf().
    {
        LineItems:
        ShowColumns(
            AddColumns(
                Filter(
                    'propinsp.tbl_WidgetOrders',
                    WidgetId = ctxWidgetId
                ),
                "Mode",    // Holds record state
                0,         // Defaults to unchanged
                "InternalId",
                Id
            ),
            "Id",
            "InternalId",
            "WidgetId",
            "CategoryId",
            "CategoryItemId",
            "Description",
            "Mode"
        )
    }
)

When I need to get this data I use this:

UpdateContext( { ctxLineItems: First( gblMyData ).LineItems } )

When I view the ctxLineItems variable, it is missing columns.  The columns in the AddColumns() are not present. I tried a test, I did the following:

ClearCollect(
    colTest,
    ShowColumns(
        AddColumns(
            Filter(
                'propinsp.tbl_WidgetOrders',
                WidgetId = ctxWidgetId
            ),
            "Mode",    // Holds record state
            0,         // Defaults to unchanged
            "InternalId",
            Id
        ),
        "Id",
        "InternalId",
        "WidgetId",
        "CategoryId",
        "CategoryItemId",
        "Description",
        "Mode"
    )
);

ClearCollect( colTest2, colTest )

When I look at the variables, colTest has all the columns but colTest2 is missing the AddColumns() columns.

If I try the below:

ClearCollect(
    colTest,
    ShowColumns(
        First( gblMyData ).LineItems,
        "Id",
        "InternalId",
        "InspectionId",
        "CategoryId",
        "CategoryItemId",
        "PhotoPath",
        "Photo",
        "Description",
        "PhotoId",
        "Mode"
    )
);

Errors, it doesn't recognize any of the column names.

 

Has anyone tried to do anything like this? This should be straight-forward, but apparently not. Am I fighting a losing battle trying to organize and properly structure my data?

 

Any thoughts or does anyone do anything different that actually works?

 

Thank you.

 

Regards,

-S

Please click Accept as solution if my post helped you solve your issue. This will help others find it more readily. It also closes the item. If the content was useful in other ways, please consider giving it Thumbs Up.

1 ACCEPTED SOLUTION

Accepted Solutions
sperry1625
Solution Supplier
Solution Supplier

I think I have this figured out.  In my App.OnStart() I have my structure declared with only the Defaults() statement. Even though I do an AddColumns() later, when I retrieve the data from the collection, gblMyData.LineItems, it defaults back to the initial definition for the data structure, not what I added after the fact. I changed my initial definitions to the following:

Set(
    gblMyData,
    {
        Dirty: false,
        Loaded: Now(),
        Details: Table( Defaults( 'tbl_WidgetDetail' ) ),
        LineItems: Table(
            Defaults( 'tbl_WidgetOrders' ),
            {
                Mode: 0,
                InternalId: 0
            }
        ),
        Photos: Table( Defaults( 'tbl_WidgetPhotos' ) )
    }
);

 Now I am getting all the columns when I grab the property. I am going to do more testing before I declare this as resolved.

 

Will keep everyone posted.

 

Thank you.

Regards,

-S

Please click Accept as solution if my post helped you solve your issue. This will help others find it more readily. It also closes the item. If the content was useful in other ways, please consider giving it Thumbs Up.

View solution in original post

1 REPLY 1
sperry1625
Solution Supplier
Solution Supplier

I think I have this figured out.  In my App.OnStart() I have my structure declared with only the Defaults() statement. Even though I do an AddColumns() later, when I retrieve the data from the collection, gblMyData.LineItems, it defaults back to the initial definition for the data structure, not what I added after the fact. I changed my initial definitions to the following:

Set(
    gblMyData,
    {
        Dirty: false,
        Loaded: Now(),
        Details: Table( Defaults( 'tbl_WidgetDetail' ) ),
        LineItems: Table(
            Defaults( 'tbl_WidgetOrders' ),
            {
                Mode: 0,
                InternalId: 0
            }
        ),
        Photos: Table( Defaults( 'tbl_WidgetPhotos' ) )
    }
);

 Now I am getting all the columns when I grab the property. I am going to do more testing before I declare this as resolved.

 

Will keep everyone posted.

 

Thank you.

Regards,

-S

Please click Accept as solution if my post helped you solve your issue. This will help others find it more readily. It also closes the item. If the content was useful in other ways, please consider giving it Thumbs Up.

Helpful resources

Announcements
Power Apps News & Annoucements carousel

Power Apps News & Announcements

Keep up to date with current events and community announcements in the Power Apps community.

Microsoft 365 Conference – December 6-8, 2022

Microsoft 365 Conference – December 6-8, 2022

Join us in Las Vegas to experience community, incredible learning opportunities, and connections that will help grow skills, know-how, and more.

Power Apps Community Blog Carousel

Power Apps Community Blog

Check out the latest Community Blog from the community!

Top Solution Authors
Top Kudoed Authors
Users online (3,574)