A dive into SubViews

The image at the top of this article shows a frame in which the same view is shown, with a frame in which again the same view is shown, ad infinitum. This is called recursion. Infinite recursion is generally not very useful, but a limited steps of views in views makes it easy to create a view out of a set of other views. This is where the SubView element comes in.

In its simplest form a SubView lets you render another view inside a part of the containing view. This can be useful for instance to display a set of photos of a person on the page that renders the properties of the Person data item (see picture). The SubView allows you to specify any view properties such as the query to load, and buttons to display. Furthermore you can enable or disable the toolbar or the search bar.

Lets walk through four other use-cases of the SubView element.

Toggle between showing one or another view

The following example shows two different SubViews that can render an address. Based on the available content a view is chosen.

VStack {
    SubView {
        show: {{ ._address[.label = "primary"] }}
        
        view {
            title: "Primary address"
            
            [datasource = pod] {
                query: "address uid={.address[primary = true].uid}"
            }
        }
    }
    SubView {
        show: {{ !._address[.label = "primary"] and .address.count }}

        view {
            title: "Secondary address"
            
            [datasource = pod] {
                query: "Address uid={.address.first.uid}"
            }
        }
    }
}

This example is a bit contrived because the query could be rewritten like this:

query: "Address uid={(.address[primary = true] or .address.first).uid}"

However it does illustrate the ability to change the presentation based on the content, and how to use a SubView for modularization.

Combine multiple views in a dashboard

When a user taps the title in the top of the screen, a menu is displayed that allows for saving the current view by giving it a name.

Menu displayed when tapping on the title

These views can be searched and labelled, and displayed as a list or in a grid just like any other data item in the memri browser. Using SubViews, it is possible to display a dynamic list of views (actually Session items) in a single view. For instance, you could create a list of views with exercise metrics rendered into charts. The following code would do just this:

The {{.}} means to select the data item of that list row, which in this list is the stored view (stored as Session).

A popup to pick one or more items out of a set

Using CVU actions, introduced in the last article, it is possible to configure a SubView to open inside a popup. The following example allows a user to add an address to the data item in the view that shows the button.

.exerciseDashboard {
    [datasource = pod] {
        query: "Session and label = 'exercise-metrics'"
    }

    [renderer = list] {
        SubView {
            view: {{.}}
            viewArguments {
                readOnly: true
            }
        }
    }
}
VStack {
    Button {
        press: openView {
            icon: "plus"
            renderAs: popup
            
            arguments {
                view {
                    title: "Add an Address"
                    editMode: true
                    defaultRenderer:list
                    
                    [datasource = pod] {
                        query: "Address"
                    }
                    
                    [renderer = list]{
                        press: [
                            link {
                                arguments {
                                    subject: {{item}}
                                    edgeType: address
                                }
                            }
                            closePopup
                        ]
                    }
                }
                viewArguments {
                    item: {{.}}
                }
            }
        }
    }
}

The above example renders a Button in a VStack. When the button is pressed it opens a popup with the view that's specified in the arguments. When the user presses on the list item in the popup, it adds the selected address to the dataItem and closes the popup.

Instead of defining the view in the press action, it's sometimes easier to just reference a view by its name and use arguments to make it dynamically fit your use case. This would change the button action to use openViewByName as you can see below:

VStack {
    Button {
        press: openViewByName {
            icon: "plus"
            renderAs: popup
            
            arguments {
                name: choose-item-by-query
                viewArguments {
                    query: "Address"
                    type: Address
                    title: "Add an Address"
                    subject: {{.}}
                    edgeType: address
                }
            }
        }
    }
}

For those curious about the "choose-item-by-query" view, this is what it looks like:

.choose-item-by-query {
    title: {{ title or "Choose a {type}" }}
    editMode: true
    
    editActionButton: toggleEditMode
    actionButton:
        addItem {
            arguments {
                type: {{type}}
            }
        }
        
    defaultRenderer: {{ renderer or "list" }}
    
    userstate: {
        selection: {{ selection }}
    }
    
    [datasource = pod] {
       query: "{query}"
    }
    
    [renderer = list]{
        press: [
            link {
                arguments {
                    subject: {{subject}}
                    edgeType: {{edgeType}}
                    distinct: {{distinct}}
                }
            }
            closePopup
        ]
    }
}

The named arguments in viewArguments used above, are used in the "choose-item-by-query" view definition as variables used in expressions such as {{dataItem}}.


Check out the new Memri forum where all Memri engineers are active to answer questions and participate in discussions. You can find all the Memri source code on the Memri gitlab.

Continue to learn about renderers or pick a topic you want to dive in from the list below.