Table of Contents

RocketDirectoryAPI Razor Snippets

Snippets for building AppTheme templates for RocketDirectoryAPI.
Copy and paste into your own AppThemes folder to get started.


Folder Structure

An AppTheme for RocketDirectoryAPI lives in a folder named:

rocketdirectoryapi.{YourThemeName}/
  1.0/
    default/
      ListView.cshtml       ← article list (front-end)
      DetailView.cshtml     ← single article detail (front-end)
      ThemeSettings.cshtml  ← module-level settings UI
      AdminDetail.cshtml    ← admin edit form for an article
    css/
    js/
    dep/
      {YourThemeName}.dep   ← dependency/install file
    resx/
      {YourThemeName}.resx  ← resource strings
  img/                      ← thumbnail shown in theme picker

RocketDirectoryAPI is different from RocketContentAPI: articles are full database records (not rows in a module). The module has separate list and detail pages.


Example Empty ListView.cshtml

The article list, typically rendered into a container via AJAX.

@inherits RocketDirectoryAPI.Components.RocketDirectoryAPITokens<Simplisity.SimplisityRazor>
@AssignDataModel(Model)
<!--inject-->
<div class="w3-section">

@foreach (var articleData in articleDataList.GetArticleList())
{
    if (!articleData.IsHidden)
    {
        <div class="w3-card w3-margin-bottom">
            <a href="@DetailUrl(moduleData.DetailPageTabId(), articleData)">
                <h3>@articleData.Name</h3>
            </a>
            <p>@articleData.Summary</p>
        </div>
    }
}

</div>

@* Paging *@
@if (articleDataList.RecordCount > sessionParams.PageSize)
{
    @RenderTemplate("ArticlePaging.cshtml", moduleData.ModuleRef, appThemeDefault, Model, true)
}

Example Empty DetailView.cshtml

The single article detail page.

@inherits RocketDirectoryAPI.Components.RocketDirectoryAPITokens<Simplisity.SimplisityRazor>
@AssignDataModel(Model)
<!--inject-->
@if (articleData != null && articleData.Exists)
{
    <div class="w3-section">

        <h1>@articleData.Name</h1>
        <p>@articleData.Summary</p>

        @if (articleData.GetImage(0).RelPath != "")
        {
            <img src="@articleData.GetImage(0).RelPath" alt="@articleData.GetImage(0).Alt" class="w3-image" />
        }

        <div>@Raw(articleData.RichText)</div>

    </div>
}

Reading Article Data

articleData is typed — use its properties directly or fall back to info.GetXmlProperty.

@{
    var info = articleData.Info;
}

@* typed shortcut properties *@
<h1>@articleData.Name</h1>
<p>@articleData.Summary</p>
<div>@Raw(articleData.RichText)</div>
<span>@articleData.PublishedDate.ToString("d MMM yyyy")</span>
<span>@articleData.Ref</span>

@* raw XML for custom fields *@
<p>@info.GetXmlProperty("genxml/textbox/customfield")</p>
<p>@info.GetXmlProperty("genxml/lang/genxml/textbox/customlangfield")</p>
@{ var isActive = info.GetXmlPropertyBool("genxml/checkbox/active"); }
@{ var qty      = info.GetXmlPropertyInt("genxml/textbox/qty"); }

Article Images

@* first image only *@
@{
    var img = articleData.GetImage(0);
}
@if (img.RelPath != "")
{
    <img src="@img.RelPath" alt="@img.Alt" class="w3-image" />
}

@* all images *@
@foreach (var img in articleData.GetImages())
{
    if (img.RelPath != "")
    {
        <img src="@img.RelPath" alt="@img.Alt" class="w3-image" />
    }
}

Article Documents and Links

@* documents *@
@if (articleData.GetDocList().Count > 0)
{
    <ul>
    @foreach (var doc in articleData.GetDocs())
    {
        <li><a href="@doc.RelPath" target="_blank">@doc.FileName</a></li>
    }
    </ul>
}

@* links *@
@if (articleData.GetLinkList().Count > 0)
{
    @foreach (var lnk in articleData.Getlinks())
    {
        <a href="@lnk.Url" class="w3-button w3-theme">@lnk.Name</a>
    }
}

Models (Price Variants)

@foreach (var model in articleData.GetModels())
{
    <div>
        <span>@model.Name</span>
        <span>@model.Ref</span>
        <span>@model.BestPriceDisplay</span>
    </div>
}

@* or just show the article best price range *@
<span>@articleData.BestPriceDisplay</span>
<span>@articleData.BestMinimumDisplay – @articleData.BestMaximumDisplay</span>

Categories

@* categories the current article belongs to *@
@foreach (var catData in articleData.GetCategories())
{
    <a href="@ListUrl(moduleData.ListPageTabId(), catData)">@catData.Name</a>
}

@* full category list (navigation/filter use) *@
@foreach (var catData in categoryDataList.GetCategoryList())
{
    if (!catData.IsHidden)
    {
        <a href="@ListUrl(moduleData.ListPageTabId(), catData)">@catData.Name</a>
    }
}

@* check if article is in a specific category *@
@if (articleData.IsInCategory(categoryData.CategoryId))
{
    <span>@categoryData.Name</span>
}

Properties and Tags

Properties are global taxonomy items (tags, attributes, filters).

@* tags the article has assigned *@
@foreach (var prop in articleData.GetProperties())
{
    <span class="w3-tag">@prop.Name</span>
}

@* properties by group *@
@foreach (var prop in articleData.GetProperties("colour"))
{
    <span>@prop.Name</span>
}

@* test if article has a specific property by ref *@
@if (articleData.HasProperty("featured"))
{
    <span class="w3-badge w3-theme">Featured</span>
}

@* clickable tag buttons with AJAX reload *@
@TagJsApiCall(moduleData, "#articlelistcontainer", sessionParams)
@foreach (var prop in propertyDataList.GetPropertyList())
{
    @TagButton(prop.PropertyId, prop.Name, sessionParams)
}
@TagButtonClear("Clear", sessionParams)

Reviews

@{ var reviews = articleData.GetReviews(); }
@if (reviews.Count > 0)
{
    <div>
        <span>@articleData.ReviewScore / 5 (@articleData.ReviewCount reviews)</span>
        @foreach (var review in reviews)
        {
            <blockquote>
                <p>@review.Comment</p>
                <footer>@review.Name – @review.ReviewDate.ToString("d MMM yyyy")</footer>
            </blockquote>
        }
    </div>
}

URL Helpers

@* link to detail page for an article *@
<a href="@DetailUrl(moduleData.DetailPageTabId(), articleData)">@articleData.Name</a>

@* link to detail page scoped to a category *@
<a href="@DetailUrl(moduleData.DetailPageTabId(), articleData, categoryData)">@articleData.Name</a>

@* link to list page *@
<a href="@ListUrl(moduleData.ListPageTabId())">All items</a>

@* link to list page filtered by category *@
<a href="@ListUrl(moduleData.ListPageTabId(), categoryData)">@categoryData.Name</a>

Property Filters (AJAX)

Checkboxes that refresh the list without a full page reload.

@* put JS call helper near the list container *@
@FilterJsApiCall(moduleData, sessionParams)

@* render filter checkboxes per property group *@
@foreach (var group in moduleData.GetPropertyModuleGroups(catalogSettings))
{
    <div class="w3-margin-bottom">
        <strong>@group.Value</strong>
        @foreach (var prop in propertyDataList.GetPropertyList(group.Key))
        {
            <label>
                @FilterCheckBox(prop.PropertyId.ToString(), prop.Name, "#articlelistcontainer", articleData.HasProperty(prop.PropertyId))
            </label>
        }
    </div>
}
@FilterClearButton("Clear filters", "#articlelistcontainer")

Reading Module Settings

@{
    var cssClass  = moduleData.GetSetting("cssclass");
    var imageSize = moduleData.GetSettingInt("imageresize");
    var itemLimit = moduleData.GetSettingInt("itemlimit");
    var defaultCatId = moduleData.DefaultCategoryId;
    var listTabId    = moduleData.ListPageTabId();
    var detailTabId  = moduleData.DetailPageTabId();
}
<div class="w3-section @cssClass">
    @* content *@
</div>

Example ThemeSettings.cshtml

All field xPaths must use the genxml/settings/ prefix.

@inherits RocketDirectoryAPI.Components.RocketDirectoryAPITokens<Simplisity.SimplisityRazor>
@AssignDataModel(Model)
@{
    var info = moduleDataInfo;
    AddProcessDataResx(appTheme, true);
}
<div class="w3-row">

    <div class="w3-third w3-padding">
        <label>CSS Class</label>
        @TextBox(info, "genxml/settings/cssclass", "class='w3-input w3-border'", "")
    </div>

    <div class="w3-third w3-padding">
        <label>Image Resize (px)</label>
        @TextBox(info, "genxml/settings/imageresize", "class='w3-input w3-border'", "1024")
    </div>

    <div class="w3-third w3-padding">
        <label>Items per page</label>
        @TextBox(info, "genxml/settings/pagesize", "class='w3-input w3-border'", "12")
    </div>

    <div class="w3-third w3-padding">
        <label>Columns</label>
        @DropDownList(info, "genxml/settings/columns", "1:1 Column,2:2 Columns,3:3 Columns,4:4 Columns", "class='w3-input w3-border'", "3")
    </div>

    <div class="w3-third w3-padding">
        <label>Background Color</label>
        @DropDownList(info, "genxml/settings/backgroundcolor", W3Utils.W3colors(), "class='w3-input w3-border'", "normal")
    </div>

    <div class="w3-third w3-padding">
        <label>Show Filters</label>
        @CheckBox(info, "genxml/settings/showfilters", "Enable property filters", "class='w3-check'")
    </div>

</div>

Example AdminDetail.cshtml

The edit form for a single article in the admin panel.

@inherits RocketDirectoryAPI.Components.RocketDirectoryAPITokens<Simplisity.SimplisityRazor>
@AssignDataModel(Model)
@{
    var info = articleData.Info;
}

<div class="w3-row">

    <div class="w3-col w3-padding" style="width:100%">
        <label>Name</label>
        @TextBox(info, "genxml/lang/genxml/textbox/articlename", "id='articlename' class='w3-input w3-border' autocomplete='off'", "", true, 0)
    </div>

    <div class="w3-col w3-padding" style="width:100%">
        <label>Summary</label>
        @TextArea(info, "genxml/lang/genxml/textbox/articlesummary", "class='w3-input w3-border' rows='4'", "", true, 0)
    </div>

    <div class="w3-col w3-padding" style="width:50%">
        <label>Ref</label>
        @TextBox(info, "genxml/textbox/articleref", "class='w3-input w3-border'", "")
    </div>

    <div class="w3-col w3-padding" style="width:50%">
        <label>Hidden</label>
        @CheckBox(info, "genxml/checkbox/hidden", "Hide this item", "class='w3-check'")
    </div>

</div>

Quick Reference

What Code
Article name (lang) articleData.Name or info.GetXmlProperty("genxml/lang/genxml/textbox/articlename")
Article summary (lang) articleData.Summary
Article rich text (lang) @Raw(articleData.RichText)
Article ref articleData.Ref
Article published date articleData.PublishedDate
Article is hidden articleData.IsHidden
Article first image articleData.GetImage(0).RelPath
Article all images articleData.GetImages()
Article docs articleData.GetDocs()
Article links articleData.Getlinks()
Article categories articleData.GetCategories()
Article properties articleData.GetProperties()
Article properties by group articleData.GetProperties("groupref")
Test property on article articleData.HasProperty("ref")
Article models articleData.GetModels()
Best price display articleData.BestPriceDisplay
Article reviews articleData.GetReviews()
Review count / score articleData.ReviewCount / articleData.ReviewScore
Article list articleDataList.GetArticleList()
Article list (rows) articleDataList.GetArticleRows(3)
Record count articleDataList.RecordCount
Category name categoryData.Name
Category image categoryData.GetImage(0).RelPath
Category children categoryData.GetDirectChildren()
Full category list categoryDataList.GetCategoryList()
Detail URL @DetailUrl(moduleData.DetailPageTabId(), articleData)
List URL @ListUrl(moduleData.ListPageTabId(), categoryData)
Module setting (string) moduleData.GetSetting("fieldname")
Module setting (int) moduleData.GetSettingInt("fieldname")
Module default category moduleData.DefaultCategoryId
Filter checkboxes @FilterCheckBox(id, name, "#container", selected)
Filter JS call @FilterJsApiCall(moduleData, sessionParams)
Tag button @TagButton(propertyId, name, sessionParams)
Tag JS call @TagJsApiCall(moduleData, "#container", sessionParams)
Render paging @RenderTemplate("ArticlePaging.cshtml", moduleData.ModuleRef, appThemeDefault, Model, true)