JavaScript & Ajax

Rapido ships with a very small, clean and powerful package of JavaScript classes – including the tiny but powerful Ajax templating engine called Handlebars, which makes it very easy to create client-side generated content. And nothing more – no jQuery, no Angular, no nothin’.

Dynamicweb Rapido is vanilla JavaScript and will continue to be so – and we strongly advise you to take the same approach.

The reasons are many:

  • Most frameworks include stuff which will never be used and which will only bloat your project
  • Pure JavaScript is more futureproof – there’s no saying which framework will be popular next
  • Pure JavaScript often supplies simpler and more maintainable solutions to a problem
  • Many of the things JavaScript made possible a few years ago can now be done with clean CSS

So while we agree that the MVC approach supplied by e.g. Angular is great, simpler and more maintainable solutions will often be available directly in JavaScript. For instance, mobile navigations, modals and dropdown menus can now be made in pure CSS – which is what we have done in Rapido.

We also strongly advise you to not create any script blocks directly in your templates, other than the script templates for rendering. And this is very important. It will keep your templates junk-free, and the next time you visit the template it will be much easier to focus on the design. There are a very few circumstances where it is not possible to avoid. Fx. when supply the correct variant object, as we have done in the product template. 

Where JavaScript really shines, is when working with code that must be client side. The greatest example of this is when using the concepts of Ajax.

Rapido uses the widely-known Handlebars.js framework for Ajax, i.e. updating part of a page asyncronously. You can read more about Handlebars.js here.

Previous versions of Rapido primarily used a small Ajax templating engine called Dynamo – it is documented below and still included for backwards compatibility.

It also means that every time you need Ajax, you will be implementing exactly the same way. Since most client side changes can be handled with JSON + Handlebars/Dynamo, you should get used to the idea that Ajax is the go-to method for updating small areas of a page. Instead of implementing complex JavaScript solutions to e.g. update a mini-cart, simply:

  • Design a JSON feed for the products in cart
  • Build the necessary script templates
  • In your design, use the Dynamo methods to update the content when a new product is added to cart

You are, of course, still free to use any other templating engine, if you have a particular favorite. We use a homebrewed engine mainly to keep the code as simple and clean as possible, while supplying just the methods and features necessary for implementing with Dynamicweb.

When you need to update only a part of a page, the best way to do this is doing some kind of Ajax. On Rapido do it by creating the data needed in the JSON format and then use JavaScript to get the data and render it client side.

We need something that can make this task very easy to do, and this is where a small helping class is needed. On Rapido we use Handlebars.js for rendering client side templates. We also supply a small optional wrapper called HandlebarsBolt.js to make it easy to work with. Here is how to work with both.


Basically, what Handlebars does is take data from a JSON feed or object, and then compile the data into a script template. A very simple example of the template could look like this:

<script id="MyProduct" type="text/x-template"> <div style=”background-color: green; color: white”> {{ProductName}} </div> </script>

And a very simple example of the JSON feed could look like this:

{ "ProductName": "Blue Bike X33" }

Then when Handlebars has done what it should do it will look like this on your page - Blue Bike X33


When you are going to build the script templates for Handlebars, there is one important little thing that may improve your templates a lot for future functionality. The case is that Handlebars always expects the root element in your JSON feed to be an object. But that is certainly not always the case, sometimes it may be a list.

An example is that of your product list page, which consist of a lot of stuff from a JSON feed, facets, products, some kind of pagination and so on. The root of the whole feed is an object, but if we want to update only the product list with new products or change the template, the feed/JSON data used will have a root type of list.

We must take care of that while building the templates. To do this simply add the “list jocker” around your template like this:

<script id=”MyList” type="text/x-template"> {{#.}} <div>{{productName}}</div> {{/.}} </script>

To work efficiently with Handlebars on Rapido, and not need to do exactly the same task multiple times, Rapido comes with a little wrapper class names “HandlebarsBolt”.

HandlebarsBolt needs a root container where it can throw in the rendered templates for a given JSON feed. To define this, put the class “js-handlebars-root” on the element you wish to be the root container. Then that element must also have the attribute “data-template” which refers to the id of the root script template you want to be rendered. And it must also have the attribute “data-json-feed” which refers to the feed.

Optional attributes available for the HandlebarsBolt root element are:




Refers to the script template id of a pre-rendering template


If you want a preloader to be shown until the rendering is done, you have two possibilities. “minimal” or “overlay”

The script templates must have the attribute type="text/x-template" to be unseen from the normal browser rendering, but recognized by the auto initializing function in HandlebarsBolt.

Your root container could for example look like this:

<div id=”ProductContainer” class=”js-handlebars-root” data-template=”MyProduct” data-json-feed=”/Default.aspx?ID=52&feed=true” data-pre-render-template=”ProductPreRender” data-preloader=”overlay”>

The smart thing here, is that if you have made your script templates with the correct element id’s, and the JSON feed works and is properly formatted, no more is needed for this to work.


Creating Ajax with Dynamo is quite simple – and requires only knowledge of plain HTML and CSS (besides how to use the engine, of course).

You can find examples of implementations in the /Templates/Designs/Rapido/Master.cshtml template as well as the /Templates/Designs/Rapido/eCom/ProductList/AjaxProductList.cshtml template.

At the most basic level, start by creating a container like this:

<div class="js-ajax-container" id="myAjaxList" data-template="myAjaxListItem" data-json-feed="urlToTheJsonFeed" div></div>

Then create the markup template:

<script id="myAjaxListItem" type="text/x-template"> <div></div> </script

The variable must be inside markup – or it will fail.

The curly-brackets annotation – {{keyname}} – is the standard annotation used by most templating engines, e.g. Mustache.js. We use it because it is stable, easy to spot, and widely employed.

If you want to create table rows, the container must be of the type table, thead, tbody, or tfooter – see the mini cart part of Master.cshtml for an example.

Rendering sub-items from the feed is just as straight forward: 

<script id="myAjaxListItem" type="text/x-template"> <div> <div id=”Variants” data-template=”variantItem”></div> </div> </script> <script id="variantItem" type="text/x-template"> <div>{{name}}</div> </script>

The sub blocks must use normal element tag names instead of the script/x-template, as you cannot put script elements inside script elements. To make the sub element render the content from JSON, the ID of the element must be the same as the key for the list from JSON you want to iterate.

The main container must use the js-ajax-container class – this is the class which Dynamo looks for when auto-initializing. But you have access to several additional properties:





The URL for the JSON feed to retrieve data from.

Automatically updated if Dynamo is used for updating. Obligatory.


The ID for the x-template to use.

Can also be set via the key “template” in the JSON feed – this overrules the ID set on this attribute.


none, minimal, or overlay

To use overlay the page must contain an element with ID=”content” to let Dynamo know which content to dim and where to place the preloader.



By far the most advanced little gem in Dynamo. If true, the setting is saved in a cookie and Dynamic saves the data in a single-page cache. This makes it possible to change views in a very fast and easy way – e.g. when changing a product list from grid-view to list-view.



If set to ‘false’, Dynamo does not auto-initialize. This is useful if you want e.g. the minicart to only get content when the user mouses over the cart. This saves calls to the server and leads to a faster load time.


The ID for the script template to use.

The pre-render template should not contain data, but is used to make a grid of boxes for rendering while waiting for the final data to load. See Paragraph/ProductsRender.cshtml for an example.


The ID of the script template which should render if no results are returned.

For an example, please see the Typehead search field.

Most of what Dynamo does happens in the background – but you do have access to a number of methods, and this section will give you an introduction to some of the most commonly used ones.


UpdateTemplate(id, template)

This updates the template for a given Ajax container.

  • id: The id of a particular Ajax container
  • template: The id of the new template

You can use this method to e.g. change views on a product list – here called on a button:

onclick="Dynamo.UpdateTemplate('Products', 'productItem')”


UpdateContent(containerId, url, updateUrl)

Use this to update the content of a given Ajax container, e.g. when clicking on a facet in a product list.

  • containerId: the id of a particular Ajax container
  • url: an URL to request new data from
  • updateUrl: true/false – if true, the browser URL will be updated

With this method, you can modify the data received by simple using parameters, added to the URL. For instance, to go to page two on a product list, you simply add &pagenum=2 to the URL. You can learn much more about this approach by examining Facets.js


AddContent(containerId, url)

Adds content to an Ajax container – e.g. to a product list.

  • containerId: the id of a particular Ajax container
  • url: an url to request new data from

For an example implementation check out LoadMore.js

For more advanced examples you can check out Variant.js – but please note that this is a complex example, which may be hard to follow if you’re not used to this kind of code.

Dynamo does not supply you with a way to work with conditionals – and since Razor is server side, and script templates are client side, you should generally NOT use Razor conditionals directly in your script templates.

The only circumstance where it makes sense to use C#/Razor conditionals in a template is if you want to use it one a server-side setting which is not changed dynamically, e.g. one of your website settings.

So how do you then hide, select, or disable content?

Dynamo – and most other templating engines – solves this by creating the conditional in a JSON feed, and having it supply a markup attribute or CSS class. For an example, open the Designs/Rapido/Json/ecom/ProductList/AjaxProductList.cshtml template (u-hidden).

While hiding content like this is a very common tactic, it is not always the best approach.

For instance, if a price should only be shown to a specific user, it would be much better to simply change templates for the price element.

While it is technically possible to create a small custom language in Dynamo for creating conditionals, we believe that the approach taken above helps you keep your code clean and maintainable – after all, conditionals make your code more complex, harder to read, and harder to maintain for other members of the project. It also means that there is a clean cut between data and logic – and the design.

Data may live forever, designs change as time goes on.

So if you put hard work into designing a data structure, you may create something that will be used for a very long time – maybe even past the next full site re-design. Plus, a rock-solid data design will also allow you to focus on implementing great designs.

The first rule of working with Ajax is this:

  • FIRST design your data, THEN create the templates which render the data

Since Rapido uses JSON feeds as a data source for Ajax, it’s very important that you learn how to design JSON feeds correctly and in the easiest manner.

We recommend that you use Razor/C# to generate your feeds – that will supply you with clean, understandable code with little risk of errors, and it will be very easy to add and/or reconfigure your data as necessary.

A very basic example of how to generate your feed using Razor/C# can be found in /Templates/Designs/Rapido/Json/ItemPublisher/List/CasesList.cshtml.

Open this template and read the next sections.

When designing JSON data, you start by creating the object definitions. Each object is equal to the data needed for one design template. This template may be repeated, which is done by creating a list of objects. All object definitions must be created inside the @functions {} block.

Since Dynamo uses JSON lists to render templates, any template object you may need must be in a list – even if you only need one item.

In the CaseList template we have “feedObject” rendered as a list containing one item; the root object for our Case list rendering. This object, the Root object, contains the list of cases, a list of available solution types and a string telling the solution type that is selected.

When you design the objects (Models), the top model must be at the bottom. That way Visual Studio and C# will know that the other objects, you put inside, exist. In this case the object “SolutionType” and “Case”.

In the object definition we decide which data we want to be available. This will mostly consist of strings or new lists of objects. We strongly encourage you to always set a unique ID property on each object – this will make it easier to track down any problems, should they occur. Furthermore, the cache in Dynamo can use the unique ID, which means that you will easily be able to retrieve that exact object from the cache, if necessary.

You can now put the correct data into the object definitions. Code hinting should help you see which properties are available on the object you defined before.

As you can see in the CaseList example, the rest of the work is very easy. Just link the data that you are used to get via TemplateTags or the ViewModel, and loop through any lists of data that you want to render.

At the end of our code block we simply add all the newly created objects to our root list, serialize it to perfect JSON and print it out as clean text on our Razor page.

As JSON is somewhat error prone, you should always verify that your JSON lists are being rendered as you want them to be – chances are, the feed is the place to look.

To validate your JSON feed output:

  • In your frontend, right-click and Inspect
  • Go to the Network page and filter so you only see XHR content
  • Refresh the page – your data feeds should appear
  • Right-click the feed you want to inspect and click Open in a new tab
  • Your JSON feed will open in a new tab
  • Select the feed output
  • Copy-paste it into the JSONLint web tool
  • Click Validate JSON

If it validates, and something is still wrong it may be the index that is not set up correctly, a variable is null or you have a typo.

When implementing, sometimes you may need to point to a specific PageID for e.g. the page with your product catalog feed. However, using a variable containing the hardcoded ID is not a very dynamic approach.

Instead you should use the Navigation tag system to solve the task:

  • Log in to the CMS
  • Locate the page you want the PageID from - e.g. the one with the main Product Catalog.
  • Go to Page properties > Options and click on Navigation
  • Write a unique tag name, e.g. “ProductsFeed”.

Then, in the templates where you need it, in the top of the template declare the variable:

@{ Int productsPageId = GetPageIdByNavigationTag("ProductsFeed"); }

While the Dynamo template engine should be used for Ajax/Client side rendering in most circumstances, there will still be areas where small chunks of scripting will be needed.

For maintenance reasons, we advise you to keep your scripts very clean and simple, to keep the code as generic as possible, and to follow the coding style already in place.

In Rapido, we supply a small handful of JavaScript classes – here is what they do and how you use them.

This has only one purpose; making it possible to disable and add a preloader to a button, after clicking it. This works especially well with forms, as it makes it visually clear that the form has been submitted while also hindering double submissions.

On the regular button/form submit button, simply add: onclick="Buttons.LockButton(event)"

Cart.js is a small class containing scripts related to the mini cart and the cart in general. Amongst other things, it makes the floating mini cart possible, and it makes client side cart actions available.

The floating mini cart is quite simple. You can have one floating mini cart, and it must have the element id “FloatingMiniCart”. The rest is automatic.

There are four cart actions available:

  • EmptyCart(this)

To use them, you use them on your buttons – most often by putting them inside an onclick or onmouseover element attribute.

Cart commands are commands used by Dynamicweb to manipulate the card, e.g. “&cartcmd=add”, “&cartcmd=emptycart”, plus the URL parameters you wish to add, like for example “&Quantity=1”. You can read more about cart commands in the manual.

For the mini cart, the following action updates it and toggles mouseover events:


Carousel.js is the complex solution for creating carousels of blocks, images, etc. This module is using for creating carousels using our paragraphs. To use it for your purposes you should follow the next markup:

<div class="carousel js-carousel-container" id="uniqueID"> <div class="carousel__container"> <div class="carousel__slide">Some slide content</div> <div class="carousel__slide">Another slide content</div> </div> </div> <div class="js-carousel-data"> <div class="carousel-prev-btn" onclick="Carousel.GetPreviousSlide('uniqueID', true)"></div> <div class="carousel-next-btn" onclick="Carousel.GetNextSlide('uniqueID', true)"></div> </div>

Containers with the .js-carousel-data class can have the following data-attributes:

Attribute Value Comment


“horizontal”, “vertical”
Default: “horizontal”

Direction of sliding


Integer number
Default: 5

How much slides will be showed on the screen in the same time


Integer number
Default: 1

How much slides will be moved per click


Integer number, time in seconds
Default: 0

Time between carousel sliding. No auto-sliding if parameter equals to 0.

Expand.js is the new simple solution to expanding and collapsing blocks on checkbox/radio clicking. To use it just add this data-attribute to your control: data-expand="SomeTrigger" and add another data-attribute with the same name to your blocks: data-trigger="SomeTrigger".

You can have any count of blocks, which will be expanded/collapsed by your control as well as any count of different controls which will show/hide the only block. To hide your blocks at start, when trigger-checkbox is not checked, use css class .expandable--collapsed. To invert behavior (show if unchecked, hide if checked) use class .js-expand-hide on your blocks. This plugin is completely compatible with RememberState.js.

This is example of using:

<input type="checkbox" id="myCheckbox" data-expand="myCheckboxTrigger" /> <div class="expandable--collapsed" data-trigger="myCheckboxTrigger">Hey!</div> <div class="js-expand-hide">Checkbox is unchecked</div>

The Facets.js class collaborates with Dynamo to modify the URL parameters when clicking facets on and off. The clickable facet element does not have to be a checkbox – you can use e.g. color boxes, tags, images, etc.

Facets.js is very easy to use. On your clickable facet item element, add: 

onclick="Facets.UpdateFacets(this, 'PRODUCT_DYNAMO_AJAX_CONTAINER_ID');" name="QUERY_PARAMETER” value="VALUE"

For a full implementation, look in /Templates/Designs/Rapido/eCom/Nolist/ProductsRender.cshtml

Filter.js is a very simple module, which allows to filter your list via text-input. For example, if you have long list of options and you want to give users ability quickly find something in the list.

To use this module, you should have some text input with attribute onkeyup="Filter.FilterItems(event)". Place your list-wrap near this input with class .js-filter.

Each option which should be filtered should have special data-attribute data-filter-value="some-text". This approach allows to filter any data, like images or something else.

It will look like this:

<input onkeyup="Filter.FilterItems(event)" /> <ul class="js-filter"> <li data-filter-value="red">Red color</li> <li data-filter-value="orange">Orange color</li> <li data-filter-value="blue">Blue color</li> </ul>

The ImageList.js class is very basic – it simply changes the URL for a main image when hovering over thumb images. To use it:

  • Add “js-thumb-btn” to all your thumbnails class attributes
  • Then add the “data-for” attribute, and type in the element id for the large image, you wish to render the image on.

If you want selections on the hovered thumbs, you must use the CSS classes found in /css/base/components/_thumbs.less

For a full implementation, look in the design folder /eCom/Product/Product.cshtml

The LoadMore.js class makes the advanced features of the “Load more” concept in the product list possible, using the pagination data from Dynamicweb. When creating a Load more button, start by adding: onclick="LoadMore.Next(this)" to the button element. Then you must set these attributes:

  • data-current=”CURRENT_PAGE”
  • data-page-size=”PAGE_SIZE”
  • data-total=”TOTAL_PAGES”

You may also wish to add disabled or hidden states on the button, for when there are no more pages. For a full implementation, look in the design folder /Paragraph/ProductsRender.cshtml

Maps.js exists to make it easy to render Google maps on Rapido. Maps generated by this script can include multiple markers, and add information to the marker info window. An example of how to use it can be found in /Templates/Designs/Rapido/Paragraph/Maps.cshtml.

Start by creating a map container with a canvas inside:

<div class="map-container"> <div id="MapCanvas" class="map-container__canvas"></div> </div>

Then you initialize it:

<script> document.addEventListener("DOMContentLoaded", function (event) { Maps.Init('MapCanvas', JSON_FEED); }); </script>

The Maps.Init method has two properties:

  • ElementID: The ID for the map canvas element.
  • JSON FEED: The javascript object with all the information.

The JSON feed is a list of locations with the following syntax:

[{ latitude: STRING, longitude: STRING, company: STRING, address: STRING, zip: STRING, city: STRING, country: STRING, description: STRING }]

The Polyfill.js class exists to ensure backwards browser compatibility. Don't touch it!

It currently makes the following JavaScript methods work across browsers:

  • CustomEvents
  • Closest

QueryArray is the class which makes possible to work with URLs and query strings (“?param=1&foo=abc”). You can change, remove or add any parameters in your query strings. Also you can directly get or set parameters in current URL by using getParameterFromCurrentURL and setParameterInCurrentURL methods.

The RememberState.js class is a little gem with two convenient uses:

  • Remember the state of an element (element attribute settings)
  • Set the state of a checkbox by an URL parameter

To remember the state of an element add the class “js-remember-state” on the element where you want the state to be remembered the next time the user visits the page. The element must have a unique id.

The second use case - setting the state of an element by URL – is very useful in Rapido, because it can be used to control UI elements (e.g. modals, dropdowns, etc.) with hidden checkboxes. This is a pure CSS approach rather than a JavaScript approach.

To use RememberState.js for that, simply add a parameter to the URL with the id of the checkbox as the parameter name and true/false as the value:

Search.js is a complex solution for searching products, pages or any content in feed results. It supports two feeds, and simultaneous search in two sources. The main wrap block of this plugin should look like this:

<div class="typeahead js-typeahead" id="SearchBar" data-page-size="@pageSize" data-search-feed-id="@firstFeedLink" data-search-second-feed-id="@secondFeedLink" data-result-page-id="@resultPageLink" data-groups-page-id="@groupsFeedId" data-search-type="@searchType"></div>

As you see there are many data-attributes. This is description for each of them:





Integer number

Result list length



Feed-page ID. You can add any query parameters like this: 99&abc=foo


String, optional

Second feed-page ID. You can add any query parameters like this: 99&abc=foo



The ID of a page, which will be opened on Enter key clicking. You can add any query parameters like this: 99&abc=foo



“content-search”, “combined-search”
Default: “product-search”

If you use search for products – use “product-search”, for combined search (products + content) use “combined-search”, for another situations use “content-search”

The second part of a markup for this plugin is a group selector, and it is optional. This part is for product search. It works as additional filter, which adds GroupID parameter with selected group ID to AJAX request to your product feed. Place this code just inside your first wrap block.

<button type="button" class="typeahead-group-btn js-typeahead-groups-btn" data-group-id="all">All</button> <ul class="dropdown dropdown--absolute-position u-min-w220px js-handlebars-root js-typeahead-groups-content" id="SearchBarGroupsContent"> <li class="dropdown__item" onclick="Search.UpdateGroupSelection(this)" data-group-id="bikes">Bikes</li> </ul>

data-group-id is a special parameter which will be placed in a query string as value of GroupID. This group-list completely supports feeds. So you can set this list via data-attributes to get groups from special feed.
The one of main parts of typeahead search is input control. Place it just after group selector (or instead of it).

<div class="typeahead-search-field"> <input type="text" class="js-typeahead-search-field"> </div>

This is an example of a markup, which should be placed RIGHT AFTER an <input> tag. It is an example for combined search, so you can use just the first block if you don’t want to make your search for two feeds.

<div class="js-handlebars-root js-typeahead-search-content" id="ProductSearchBarContent" data-template="productTemplateID" data-json-feed="/Default.aspx?ID=@searchProductsFeedId&feedType=productsOnly" data-init-onload="false"></div> <div class="js-handlebars-root js-typeahead-additional-search-content" id="ContentSearchBarContent" data-template="templateID" data-json-feed="/Default.aspx?ID=@searchSecondFeedId" data-init-onload="false"></div>

The last part of a markup is a search-button. It should be placed in the end of main wrapper.

<button type="button" class="js-typeahead-enter-btn">Search<button>

So that’s all. This search supports Keyboard, so you can use arrows on your Keyboard to navigate on search results. Also you can use Enter button instead of clicking on results, or instead of start search.

While the browser usually remembers a scroll position perfectly, this is not the case when you load Ajax content – and it is very important that auto-scrolling doesn’t happen before all the content is loaded.

And so the Scroll.js class has only one purpose – remembering the scroll position.

To use Scroll.js, simply add onclick=”Scroll.SavePosition(event)” to any link leaving a page where you want the scroll position to be remembered:

<a href="" onclick="Scroll.SavePosition(event)"><img class="grid__cell-img" src="data.image" /></a>

This class exists to make it possible to interact with variants in the product list and on the product page.

The Variants.js class is by far the most complex of all JavaScript classes in Rapido, and very difficult to understand. The reasons are hard to combat – variants do not have simple, linear relations, but a mesh of links which are very difficult to comprehend by simply looking at the data.

Variants are very complex, and hard to work with. We encourage you to simply use the implemented solution. And just know that the feature is available. 

Video.js is needed for creating of background YouTube videos for paragraphs:

<div class="video-background"> <div class="video-background__container"> <div class="js-youtube-video" data-video="videoID" id="uniqueID"></div> </div> </div>

VideoID is a unique identifier of YouTube video - e.g. the videoID of is V6oUAM45FvM. But our paragraphs just need a link for a YouTube video.

This little script takes an entire website, and then enables a “wireframe” mode. It basically removes all custom CSS (Rapido + Ignite) and uses only the Base CSS project. Then it attempts to locate all images and replace them with a placeholder image block instead.

Wireframe.js also includes scripts for an upcoming comment + tools system, which will be in use when choosing Wireframe mode. The full comment system is planned for a later release.

While implementing, you will usually never have a reason for looking into this part of Rapido.