Rock Mobile Docs
App Factory
  • Welcome 👋
  • 📱Getting Started
    • Building Your First App
      • Creating An App
      • App Configuration
      • Adding Content
      • Deploying Your App
    • Lexicon
  • 🧱Essentials
    • Animations
    • Blocks
      • CMS
        • Content
        • Content Channel Item View
        • Content Collection View
        • Daily Challenge Entry
        • Hero
        • Lava Item List
        • Login
          • Using Auth0
          • Using Entra
        • Profile Details
        • Register
        • Structured Content View
        • Workflow Entry
      • Check-in
        • Check-in
      • Communication
        • Communication Entry
        • Communication List Subscribe
        • Communication View
        • SMS Conversation List
        • SMS Conversation
      • Connection
        • Add Connection Request
        • Connection Type List
        • Connection Opportunity List
        • Connection Request List
        • Connection Request Detail
      • Core
        • Attribute Values
        • Notes
        • Search
        • Smart Search
        • Quick Note
        • My Notes
      • CRM
        • Group Members
        • Person Profile
      • Events
        • Live Experience Occurrences
        • Live Experience
        • Calendar Event Item Occurrence View
        • Calendar Event List
        • Calendar View
        • Event Item Occurrence List By Audience Lava
      • Finance
        • Giving
        • Scheduled Transaction List
        • Transaction Detail
        • Transaction List
      • Groups
        • Group Attendance Entry
        • Group Edit
        • Group Finder
        • Group Member Edit
        • Group Member List
        • Group Member View
        • Group Registration
        • Group View
        • Schedule Preference
        • Schedule Sign Up
        • Schedule Toolbox
        • Schedule Unavailability
      • Prayer
        • Answer To Prayer
        • My Prayer Requests
        • Prayer Card View
        • Prayer Request Details
        • Prayer Session
        • Prayer Session Setup
      • Reminders
        • Reminder Edit
        • Reminder List
        • Reminder Dashboard
      • Security
        • Onboard Person
    • Codex
      • Application Strategy
      • XAML Styling
      • Resources
      • Documentation
    • Commands
      • Communication Commands
      • Navigation Commands
      • Media Commands
      • Utility Commands
    • Controls
      • Behaviors
        • Event To Command Behavior
        • Touch Behavior
      • Content Controls
        • Activity Indicator
        • Application Info
        • Avatar
        • Bible Audio
        • Bible Browser
        • Bible Reader
        • Campus Context Picker
          • Camera Code Reader
        • Cards
          • Block Card
          • Contained Card
          • Inline Card
          • Elements of a Card
          • Masks
          • Styling Cards With CSS
        • Context Menu
        • Countdown
        • Cover Sheet
        • Divider
        • Expander
        • Field Container
        • Flip View
        • Following Icon
        • Geo Boundary View
        • HTML
        • Icon
        • Icon Button
        • Image
        • Interaction
        • Items Collection
        • Login Status
        • Login Status Photo
        • Lottie View
        • Markdown
        • Media Player
          • Legacy
        • Notification Box
        • Paragraph Text
        • QR Code
        • Ratio View
        • Redirect
        • Responsive Column
        • Responsive Layout
        • Scroll View
        • Segment Picker
        • Styled Border
        • Styled View
        • Tag
        • Toggle Button
        • Web View
      • Developer Controls
        • Execute Command
        • Bible Book And Chapter Picker
        • Command Reference
        • Field Stack
        • Media Cast Button
        • Media Progress Bar
        • Parameter
        • Scan Code
        • Validator
        • Volume Control
        • Zone
      • Effects
        • Blur Effect
        • Safe Area Padding Effect
      • Form Fields
        • Attribute Value Editor
        • Address
        • Campus Picker
        • Check Box
        • Check Box List
        • Currency Box
        • Date Picker
        • Email Box
        • Literal
        • Marital Status Picker
        • Multi Picker
        • Number Box
        • Phone Number Box
        • Picker
        • Text Box
        • Text Editor
      • XAML Extensions
        • Boolean Value Converter
        • From Json
        • Inverse Boolean Converter
        • Nullable Guid Converter
        • On Device Platform
        • On Device Type
        • Palette Color
        • Seconds To Time String Converter
    • Field Types
    • Lava
      • Context in Lava
    • Performance
    • Tips and Tricks
      • Custom Site Attributes
      • Migrating to .NET MAUI (V6)
      • Page Anchors
    • Troubleshooting
    • Advanced Topics
      • Dynamic Content
      • Deep Linking
  • 🎨Styling
    • Introduction
    • Style Guide
      • Walkthrough
      • Colors
      • Typography
      • Utilities
      • Shell Components
      • Migrating
    • Legacy
      • Colors
      • Borders
        • Border Color
        • Border Radius
        • Border Width
      • Text
        • Background Color
        • Text Size
        • Alignment
        • Color
        • Line Height
        • Weights & Styles
      • iOS Shadows
      • Styling Components
        • Tags
        • Bible
        • Button
        • Form Fields
        • Modals
      • Custom CSS
  • 👨‍💻Developers
    • Fundamentals
    • Core & Shell Dependencies
    • Custom Blocks
    • OS Version Requirements
  • 🏭App Factory
    • Overview
    • Android Keystore
    • App Store Product Page
    • Developer Accounts
    • Image Resources
    • In-App Giving
    • Publishing Requirements
    • Push Notifications
    • Rock Logins
    • Shell Update Requirements
Powered by GitBook

Resources

  • Release Notes
  • Community Chat
  • Ask Chip

Documentation

  • Rock Manuals
  • Lava

⚙️ Powered by Rock RMS

On this page
  • Callbacks
  • Page Events
Export as PDF
  1. Essentials
  2. Advanced Topics

Dynamic Content

As you've seen you can do a lot with a Content block. While that block does allow for some dynamic ability via Lava processing, it's essentially a "one-shot" block. Whatever it renders is what you are stuck with, so to speak. Think of it like the HTML Content block. It's certainly dynamic in that you can use Lava to customize how it looks, but it doesn't allow the user to interact with it and change the content.

Or does it?

Callbacks

The content block also supports what is called Callbacks. If you have an ASP.Net background, you can think of this as a partial postback. Otherwise, just know that this allows you to change the content displayed in the Content block in response to a user action, such as tapping on a button. To do this, it adds a new Command that is available for you to use: Callback. This command allows you to send the command and parameters you define back to a special lava template defined in the Advanced Settings tab of the block.

In a previous article, we built a simple search page that linked the user out to google to perform the search. Linking out to Google is great and all, but what if we want to use the built-in universal search? Let's look at what that might look like. First, let's define the primary content of the block.

<StackLayout>
    <Rock:FieldContainer>
        <Rock:TextBox x:Name="SearchTerm"
            Label="Search" />
    </Rock:FieldContainer>

    <Button Text="Search"
            StyleClass="btn, btn-primary"
            Command="{Binding Callback}">
        <Button.CommandParameter>
            <Rock:CallbackParameters Name="Search">
                <Rock:Parameter Name="Term"
                    Value="{Binding Source={x:Reference SearchTerm}, Path=Text}" />
            </Rock:CallbackParameters>
        </Button.CommandParameter>
    </Button>
</StackLayout>

This still gives us a pretty Search text field for the user to enter a search term into, as well as a button to press. The button now calls the Callback command and we have defined our custom Action object to have a sub-command of Search. We also defined a parameter called Term that will take its value from the textbox.

Don't forget to add the Name property to the CallbackParameters; this is the name of the event and is required for callbacks to function.

Next, let's define what will happen when the user clicks the Search button. This is what we are going to put into our Callback Event in the block's settings.

<StackLayout>
    <Rock:FieldContainer>
            <Rock:TextBox x:Name="SearchTerm"
                Label="Search"
                Text="{{ Parameters.Term | Escape }}" />
    </Rock:FieldContainer>

    <Button Text="Search"
            StyleClass="btn, btn-primary"
            Command="{Binding Callback}">
        <Button.CommandParameter>
            <Rock:CallbackParameters Name="Search">
                <Rock:Parameter Name="Term"
                    Value="{Binding Source={x:Reference SearchTerm}, Path=Text}" />
            </Rock:CallbackParameters>
        </Button.CommandParameter>
    </Button>

    {% if Command == "Search" %}
        <StackLayout Margin="0,20,0,0">
            {% search query:'{{ Parameters.Term }}' entities:'group' fieldcriteria:'GroupTypeName^Serving Team' %}
                {% for result in results %}
                    <Button Text="{{ result.DocumentName | Escape }}"
                        StyleClass="btn, btn-info" />
                {% endfor %}
            {% endsearch %}
        </StackLayout>
    {% endif %}
</StackLayout>

Notice that we duplicated our original content. That is because we want the page to still have the textbox and Search button so that the user can change their search term and try again. Notice we also added the default Text property to the textbox. This will keep whatever the user entered into the textbox in place when the content is reloaded.

After all that, comes our new code. We check if the Command variable is the word Search which is what we are expecting. If found, we then use the search lava command to search our serving teams and look for any groups that match the search term the user entered ({{ Parameters.Term }}). For each result we get back, we render a button with the group name on it. If this was a full working example we would make that button do something, like go to a Rock page and pass the group Id.

So we implemented an internal Rock search system for our mobile application even though there is no "search" block available. And we did it without C# code. Now, I mentioned above that if this were a real search block we would need the "group button" to do something. As I said above, that might be going to another page and passing the Group Id in. But we could also build another <Rock:Action /> for each button that performs another Callback action and updates the UI based on the group they have selected.

Page Events

Let's set the stage because this is going to give some of you heartburn. Lava is designed and meant to be used as a formatting engine. Said another way, it's not meant to generate any content but just format content that already exists. This you probably know. Now, throw that idea out the window. We are going to use Lava in a way it was never meant to be used. You might ask why. In the simplest terms, we needed a scripting engine that you would be familiar with. You are already familiar with doing if checks and other logic with Lava, so we decided to just use what you already know. If this makes you nervous, take an antacid pill because we're diving in!

When you edit a mobile page in Rock, there is a section called Event Handler. This is Lava that will be executed when certain events happen on the page. You might be thinking, so what? I can only format data with Lava. Oh contraire. Well, normally you would be correct, but we have added a few custom bits to Lava in the mobile application. Let's start with a really simple example. First, put a Content block on your page and set the content to be:

<Label Text="{Binding PageValues.Message}" />

Now edit your page settings and put this in for the Event Handler:

{% if Event == 'Load' or Event == 'Resize' %}
    {% if Device.Orientation == "Landscape" %}
        {% setpagevalue 'Message', 'You are looking at this sideways!' %}
    {% else %}
        {% setpagevalue 'Message', 'Good to see you upright.' %}
    {% endif %}
{% endif %}

Once you deploy this you will see the proper text appear depending on which way you are holding your device. So what is going on here? Well, we set up our label to bind the Text value to PageValues.Message. The PageValues object exists on each page and is essentially a dictionary. You can store whatever values you want in it and access them. Because this object exists at the page level, it is shared between blocks.

Next, in our Event Handler we are checking the device's orientation. Depending on the value we set the Text value of the UsersValue dictionary to the string it should have.

Okay great, you're probably thinking, so I can make text appear when they rotate their phone. What good is that? Okay, how about a more useful example? Let's take a Content Channel Item List block. Suppose you wanted to display the results with a thumbnail image. This might look good on a phone in portrait orientation, but what about if the phone is rotated or if they are on a tablet? Now you have these massive thumbnails. Using the Lava Events we will adjust the number of thumbnails displayed per row. Let's setup the template (note: we are leaving out the xmlns declarations as they waste a lot of space):

<Rock:ItemsView ItemsSource="{Binding Items}">
    <Rock:ItemsView.ItemTemplate>
        <DataTemplate>
            <Rock:Image ImageUrl="{Binding Image}" />
        </DataTemplate>
    </Rock:ItemsView.ItemTemplate>
    <Rock:ItemsView.ItemsLayout>
        <Rock:GridItemsLayout Span="{Binding PageValues.Columns}" />
    </Rock:ItemsView.ItemsLayout>
</Rock:ItemsView>

Above, we are setting up a custom ItemsLayout and have specified that it should be a grid, which by default is vertical. The Span parameter specifies how many columns there will be. Since we are binding that value to PageValues.Columns we will need to set that in our Event Handler:

{% if Event == 'Load' or Event == 'Resize' %}
    {% if Device.Width > 900 %}
        {% assign columns = 4 %}
    {% elsif Device.Width > 600 %}
        {% assign columns = 3 %}
    {% else %}
        {% assign columns = 2 %}
    {% endif %}

    {% setpagevalue 'Columns', columns %}
{% endif %}

What this will give us is a grid that is 2 columns wide on really narrow screens, 3 columns on medium width screens and 4 columns on really wide screens. And, this happens each time you rotate the device, this isn't just a set once and hope it's correct until they leave the page.

So how do you know why your Event Handler is being executed? As you saw, there is an Event variable defined which will tell you the event that initiated the lava. Currently, there are two pre-defined events:

  • Load: This event is initiated when the page is loaded, but before any blocks have been instantiated.

  • Resize: This event is initiated when the available screen space has changed, such as a rotation.

We just mentioned above "pre-defined" events. You can initiate your own events with the LavaEventcommand. The name of the event you wish to trigger is specified by the CommandParameter. This means you can set up a button on-screen that will trigger a custom Lava event and then you can update your PageValues any way you wish.

Last updated 3 months ago

🧱