Power Pages

Creating a Bootstrap Carousel (Slider) using Liquid and Fetch XML

In this post, you’ll see how to build a Bootstrap carousel (aka slider), populated with data from a Dataverse table.
We query using FetchXML (which you can build using Advanced Find) and then loop through each result, populating the background image, heading and paragraph for each slide.

Quickstart – Get a result quickly by taking my snippet and making it work for you

Let’s get you some visible results quickly. For this reason, I’ve created some boilerplate code that you can copy and reuse. This contains all the stuff that wouldn’t change from one implementation to the next; not just Bootstrap’s HTML but liquid too… things like looping and dynamic slide numbering.

So if you want to get up and running quickly, all you need to focus on is:

  • Creating an advanced find to pinpoint the records you wish to display in the carousel / slider
  • Adding the logical names of the columns you wish to output

To get started, copy and paste the snippet below into a web page or template

Exactly what to change is detailed after the snippet… I’m nice like that 🙂

{% fetchxml name_of_query %}
    Paste your Fetch XML here    
{% endfetchxml %}

{% if name_of_query.results.entities.size > 0 %}
    <div id="carousel-example-generic" class="carousel slide" data-ride="carousel">
        <!-- Indicators -->
        <ol class="carousel-indicators">
            {% for result in name_of_query.results.entities %}
                <li data-target="#carousel-example-generic" data-slide-to="{{ forloop.index | minus: 1 }}" {% if forloop.first %}class="active"{% endif %}></li>
            {% endfor %}
        </ol>

        <!-- Wrapper for slides -->
        <div class="carousel-inner" role="listbox">
            {% for result in name_of_query.results.entities %}
                <div class="item {% if forloop.first %}active{% endif %}">
                <img src="{{ result.logicalNameforImagecolumn_url }}&Full=true" alt="...">
                <div class="carousel-caption">
                    <h3>{{ result.logicalNameForNameColumn }}</h3>
                    <p>{{ result.logicalNameForDescriptionColumn }}</p>
                    <a class="btn btn-primary" href="/Partial-URL/?id={{ result.guidForThisRecord }}">View Details</a>
                </div>
                </div>
            {% endfor %}
        </div>

        <!-- Controls -->
        <a class="left carousel-control" href="#carousel-example-generic" role="button" data-slide="prev">
            <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
            <span class="sr-only">Previous</span>
        </a>
        <a class="right carousel-control" href="#carousel-example-generic" role="button" data-slide="next">
            <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
            <span class="sr-only">Next</span>
        </a>
    </div>
{% endif %}

All you’d need to do to make this fully functional is to update the naming to match your table and use case.

  1. Paste your Fetch XML query (copied from Advanced Find) between the opening and closing {% fetchxml %} tags
  2. Replace all instances of ‘carousel-example-generic‘ with a meaningful name e.g. ‘upcoming-events-carousel’.
  3. Replace all instances of ‘name_of_query‘ with a meaningful name e.g. ‘upcoming_events_query’
  4. Replace ‘logicalNameForImageColumn‘ with the logical name for the image column on your table. Leave the _url part in there
  5. Replace ‘logicalNameForNameColumn‘ with the logical name for the text field you wish to use as the heading for each slide
  6. Replace ‘logicalNameForDescriptionColumn‘ with the logical name for the text field you wish to use as the description for each slide
  7. If you wish to link to another page from each slide e.g. to the registration form for an event, or to a full details page, replace ‘Partial-URL‘ with the partial URL of the web page e.g. View-Event-Details, and replace ‘guidForThisRecord‘ with the logical name for your table’s GUID (this will usually be the name of your table followed by id e.g. accountid, contactid, musdyn_trackid, etc.)

If you’re interested in how I arrived at that code and would like to create your own from scratch, here’s how…

Making the carousel from scratch

Prerequisites:

  • Create a table with an Image column
  • Populate with some sample records
  • Create table permission with at least Read privileges

Step 1 – Get a carousel up and running, cycling through placeholder content

Go to Bootstrap JavaScript documentation using the link below: https://bootstrapdocs.com/v3.3.6/docs/javascript/

This will list all the pre-made JavaScript components available to us

Select Carousel

We can see a carousel aka slider cycling through some placeholder content and, most helpfully, a HTML snippet for us to use as a starting point

Understanding the markup of Bootstrap’s carousel

Knowing what the slider is made up of will help a lot when it comes to making it dynamic. Here we go…

Analysing Bootstrap’s example HTML: Recognising patterns

What am I looking for when analysing / breaking down Bootstrap’s example markup?

Which parts are repeating – this tells us what constitutes one ‘item’ – in this example, what’s the HTML markup for one slide in the carousel. This is what we’ll place within our for loop.

I’m also looking for unique identifiers e.g. for the carousel and for each item that we’ll need to provide. Also are there any classes in the HTML for the current item only?

Here goes…

The main div for the carousel has an ID. This is important in case we were to have multiple carousels on the same page. You may notice that this is referenced elsewhere e.g. in the controls for this carousel.

Then we have the indicators. These:

  • Show how many ‘slides’ there are in total
  • Show which ‘slide’ we’re currently on
  • Allow us to skip directly to a specific slide

The indicators live in an ordered list <ol> with a class of carousel-indicators.

Each indicator is a list item <li> and hold some key information:

  • data-target specifies which carousel this indicator relates to / controls
  • data-slide-to specifies the slide this indicators links to (by numeric ID. Note these numbers start from zero… we’ll need to contend with these later)

 

Note that the first list item has a class of active

As the carousel plays, this active class is removed from the current slide and onto the next

Next we have a wrapper for the slides. This won’t change so we’ll leave it alone

Then we have the actual ‘slides’. Each ‘slide’ is a div with a class of item

Just like the indicators, note that the first item has a class of active

As the carousel plays, this active class is removed from the current slide and onto the next

The item has some child elements; an image and a caption. This is where we’ll insert the content

 

Finally, we have the Previous and Next controls. We can leave these alone. This markup remains the same for every carousel so we’ll leave this alone.

Okay first thing we’ll do is copy that example markup onto a web page…

Populating the carousel with placeholder content

This step is optional but I find it to be a useful first step to help identify any errors in my HTML before I complicate things with liquid…

What’s not too helpful is that Bootstrap’s example HTML doesn’t contain the correct number of slides, nor any caption content. Within there, we’ll add a heading 3 and a paragraph.

Without an image, the height of the carousel collapses and looks a mess. Let’s include a placeholder image for now. We can get them using an online service, https://picsum.photos

We can specify the size we need in the URL. I’m going to use the same pixel dimensions as the bootstrap example, 900 x 500

This gets us an image at 900px x 500px:

https://picsum.photos/900/500

However, we’d get the same image 3 times, so let’s amend that to get a different random image each time:

https://picsum.photos/seed/1/900/500

https://picsum.photos/seed/2/900/500

https://picsum.photos/seed/3/900/500

 

We add this to the source attribute of the image

…pop in an example heading and paragraph and we’re done with the first slide

We can then just copy and paste 2 more versions of this and tweak to make them unique

It’s important that we remove the active class from any except the first slide… only one can be displayed and active at any one time

Save, Sync and Preview. We now have a slider cycling through static content

Let’s level up now and make that dynamic, populating with data from Dataverse…

To make this dynamic, we’ll be using Liquid templating language…

Which liquid skills we’ll be using and what each one does / brings to the table

Fetch XML

Query Dataverse data. Don’t worry, we won’t need to write this ourselves. We can use Advanced Find. If you’re familiar with XRMToolbox, you might prefer to use Jonas Rapp’s excellent Fetch XML Builder

For

Allows us to loop through each item in a collection – in our example that’ll be looping through each result returned by our Fetch XML query.
As well as the looping ‘action’ it provides, we also have information about the loop in an object called forloop. This allows us to:
  • Add sequential numbering to results (we’ll use this for the navigation)
  • Check whether the current item is the first or last result (we’ll use first to determine which slide gets the ‘active’ class, meaning it’s displayed when the carousel loads)

If

Allows us to perform checks on our data / results and provide fallbacks.
Things we’ll want to check in this example:
  • Did our Fetch XML return any results?
  • Is this the first item (result) in the forloop?

Query for the records we want to display, using Advanced Find

First, we’ll use Advanced Find to retrieve the information we want to show in our carousel. Not ‘classic’ advanced find but the modern advanced find experience.

Why use modern advanced find? I was reluctant to break old habits and start using modern advanced find. However, one big help that sealed the deal for me is being able to select image columns. (Note – the image will look like gibberish in the view but all we care about is having the image url as a column in our Fetch XML, which this will give us.

I’m going to use a list of Event Sessions. I’ll start by opening that table in my model driven app.

Here, I Edit Columns to specify which columns I want to display in the slider

Next, I specify a sort order simply by clicking the column title… once for ascending order, twice for descending order. Often the requirement is to show the most recent items, so I sort descending by a date column such as Created On or Start Date (depending on the table)

Next, I create the filter. For me this is usually a date period and perhaps a status reason. You may also want to consider whether there are any columns that mark certain records as ‘featured’. We can apply basic filters using the column headings or use Edit Filters for more complex criteria like information stored on related records.

Let’s save our personal view in case we need to make changes later…

Click the view selector drop-down and choose Save as New View

Give it a meaningful name and click Save

Now, to get the fetch XML…

Open the view selector drop-down again and choose Manage and Share Views

Click the ellipsis next to your saved view and choose Download FetchXML

 

So what do we do with this code you might ask… We’re going to paste it into our template.

But we need to tell Power Pages that some fetch xml is coming and what to do with it.

We’ll type an opening and closing fetchxml tags and give our query a name, like so:

{% fetchxml event_sessions_query %}

{% endfetchxml %}

Now we can paste our fetchxml between those tags

Note – the purpose of giving our query a name is that we can refer to it later e.g. to check for the number of results and to output any results

Here goes…

First of all, let’s check for any results. We can use an if statement for this. Let’s surround the entire carousel with this. No point showing an empty slider if we have no results.

{% if event_sessions_query.results.entities.size > 0 %}

What’s that if statement all about?

Fetch XML queries in liquid return the results in an object called results.entities

Later we’ll loop through this to access our results. For now, we just want to check its size re. how many results were returned. We do that with .size

Note: .size is a handy property for liquid in general. We can use it to check whether columns are populated and many other things too.

We’ll soon get onto dynamically populating our slider but first, let’s reduce our HTML down to just one indicator and just one ‘slide’…

Paste in our boilerplate code

Replace carousel-example-generic with something meaningful like gold-sponsors-carousel. Note – there are many instances of this… the ID of the main div, in the indicators and for the previous and next buttons. You may notice sometimes it has a # before it. That’s required. It tells our code that this text is referring to an ID.

Replace everywhere that says name_of_query with something meaningful like gold_sponsors_query

Tip- that’ll be in the fetch xml tag, the if statement and the for loop

Paste your Fetch XML between the opening and closing fetch xml tags

 

Now we actually populate the HTML with data from our fetch XML query

Everywhere you see code within double curly braces, that means output something

result. Means output for the current result in the for loop

e.g. swap {{ result.logicalnameforNamecolumn }} with {{ result.cflow_name }}

Franco Musso

You may also like

Leave a reply

Your email address will not be published.

More in Power Pages