Fork me on GitHub
DNN Apps - Demo-Zone
Discover DNN-Apps - simple and elegant, easy to customize
You are here: Home  >  Apps  >  FAQ with Categories

FAQ with Categories

The following is an FAQ module with categories. It demonstrates things like

  1. Use other entities for categories
  2. Find all categories in use (to show the filter-menu) (unique, no duplicates) and ordered
  3. Change URL for category-filter
  4. Handle exotic characters in URL

On this sub-page you'll also find more views with more functionality.

Simple FAQ-List

This list just shows the questions you added - no frills, no gimmicks. All you can do is select what effect you want when you click on a questions (in the List-Presentation).

  1. How can we filter related entities through a link

Frequently asked questions (FAQ)

This is the power-mode with filtering. Note that the editor can write other things here - this is just the default text.

Filter by
  1. How can I choose between lightbox-effect or slider?
  2. What happens when categories have nasty characters?
  3. How can we filter related entities through a link

Manually selected Existing Questions

The next two examples show

  1. All questions of a predefined category
  2. All questions manually selected/sorted to be shown on this module

Demo selected category "Programming"

The demo entry already selected a category for you. Change this text and select another category by pressing Edit.

  1. How can I choose between lightbox-effect or slider?
  2. How can we filter related entities through a link

Demo Selection of Questions

Just go into the settings and select existing questions you want to show here.
  1. How can we filter related entities through a link
  2. What happens when categories have nasty characters?
Error rendering template

Look inside

Content Item

These are the values a content-editor can manage.
Name Type Value
Name System.String Programming Programming


Presentation Item

These are additional, optional presentation instructions a content-editor can manage. If none are entered, a default set (predefined by the designer) will be used.

No Presentation parameters specified, using default presentation for this item.


Template file

@using ToSic.Eav.DataSources
@{
	// Sort by Name
	var categories = CreateSource<ValueSort>(App.Data["Category"]);
	categories.Attributes = "Name";
}
<h2>Edit Categories</h2>
<p class="sc-element">Found @categories.List.Count()
	<ul class="sc-menu" data-toolbar='{"action":"new", "attributeSetName": "Category"}'></ul>
</p>
<ol>
	@foreach (var dict in categories.List)
	{
		var cat = AsDynamic(dict.Value);
		<li class="sc-element">
			<ul class="sc-menu" data-toolbar='{"entityId" : @cat.EntityId, "action":"edit"}'></ul>
		@cat.Name
	</li>
	}
</ol>

Look inside

Content Item

These are the values a content-editor can manage.
Name Type Value
Question System.String How can I choose between lightbox-effect or slider? How can I choose between lightbox-effect or slider?
Answer System.String <p>Very simple - just set it in the list-header (the edit-button where you can change the title).&nbsp;</p> <p>Very simple - just set it in the list-header (the edit-button where you can change the title).&nbsp;</p>
Categories ToSic.Eav.Data.EntityRelationship 2548,2549 2548,2549


Presentation Item

These are additional, optional presentation instructions a content-editor can manage. If none are entered, a default set (predefined by the designer) will be used.

No Presentation parameters specified, using default presentation for this item.


Template file

@using ToSic.SexyContent
@functions
{
    // variable which will contain the sorted categories
    IEnumerable<dynamic> sortedCategories;

    // Prepare the data - get all categories through the pipeline
    public override void CustomizeData()
    {
        // get all categories of these questions, then get the distinct entities 
        // this could all be done on 1 line, but it would be harder for people who don't know LINQ yet
        var questionsInThisModule = AsDynamic(Data["Default"].List);
        var categoriesUsed = questionsInThisModule.SelectMany(q => ((List<DynamicEntity>)q.Categories));
        var distinctCategories = categoriesUsed.Select(AsEntity).Distinct();    // Distinct only works reliably when cast as entity
        sortedCategories = AsDynamic(distinctCategories).OrderBy(q => q.Name);
    }
    
}
<h2 class="sc-element">@ListContent.Title @ListContent.Toolbar</h2>
<div>@Html.Raw(ListContent.Introduction)</div>

<div>
    <strong>@App.Resources.FilterBy </strong>
    <select id="ddlFeatureFilter">
        <option value="all">@App.Resources.ShowAll</option>
        @foreach (var cat in sortedCategories)
        {
            <option value="@cat.EntityId">@cat.Name</option>
        }
    </select>
</div>

<ol>
    @foreach (var q in AsDynamic(Data["Default"].List))
    {
        <li class="sc-element faq-set" data-tags="@String.Join(",", ((List<DynamicEntity>)q.Categories).Select(a => AsDynamic(a).EntityId))">
            @q.Toolbar
            <a class="faq-question" style="cursor: pointer">
                @q.Question
            </a>
            <div class="faq-answer" style="display: none">@Html.Raw(q.Answer)</div>
        </li>
    }

</ol>

<script src="@App.Path/assets/faq.js" data-enableoptimizations="true"></script>
<script>
	$(document).ready(function() {
		initFaqSection("DnnModule-" + @Dnn.Module.ModuleID, "@ListPresentation.ShowEffect");
	});
</script>

Look inside

Content Item

These are the values a content-editor can manage.
Name Type Value


Presentation Item

These are additional, optional presentation instructions a content-editor can manage. If none are entered, a default set (predefined by the designer) will be used.

No Presentation parameters specified, using default presentation for this item.


Template file

@using ToSic.SexyContent
<h2 class="sc-element">@ListContent.Title @ListContent.Toolbar</h2>
<div>@Html.Raw(ListContent.Introduction)</div>
<ol>
    @foreach (var q in AsDynamic(Data["Default"].List))
    {
        <li class="sc-element faq-set" data-tags="@String.Join(",", ((List<DynamicEntity>)q.Categories).Select(a => AsDynamic(a).EntityId))">
            @q.Toolbar
            <a class="faq-question" style="cursor: pointer">
                @q.Question
            </a>
            <div class="faq-answer" style="display: none">@Html.Raw(q.Answer)</div>
        </li>
    }
</ol>

<script src="@App.Path/assets/faq.js" data-enableoptimizations="true"></script>
<script>
	$(document).ready(function() {
		initFaqSection("DnnModule-" + @Dnn.Module.ModuleID, "@ListPresentation.ShowEffect");
	});
</script>

Look inside

Content Item

These are the values a content-editor can manage.
Name Type Value
Title System.String Demo selected category "Programming" Demo selected category "Programming"
Introduction System.String <p>The demo entry already selected a category for you. Change this text and select another category by pressing Edit. </p> <p>The demo entry already selected a category for you. Change this text and select another category by pressing Edit. </p>
Category ToSic.Eav.Data.EntityRelationship 2549 2549


Presentation Item

These are additional, optional presentation instructions a content-editor can manage. If none are entered, a default set (predefined by the designer) will be used.

No Presentation parameters specified, using default presentation for this item.


Template file

@using ToSic.Eav.DataSources
@using ToSic.SexyContent
@functions{
    // Prepare the data - get all categories through the pipeline
    public override void CustomizeData()
    {
        // new features in 6.1 - the App DataSource CreateSource<App> and also the RelationshipFilter
        var qsOfCat = CreateSource<RelationshipFilter>(App.Data["QandA"]);
        qsOfCat.Relationship = "Categories";
        qsOfCat.Filter = Content.Category.Count > 0 ? Content.Category[0].Name : "";
        var sorted = CreateSource<ValueSort>(qsOfCat);
        sorted.Attributes = "EntityTitle";
        Data.In.Add("QandA", sorted["Default"]);
    }
}

<h2 class="sc-element">@Content.Title @Content.Toolbar</h2>
<div>@Html.Raw(Content.Introduction)</div>
<ol>
    @foreach (var q in AsDynamic(Data["QandA"]))
    {
        <li class="sc-element faq-set" data-tags="@String.Join(",", ((List<DynamicEntity>)q.Categories).Select(a => AsDynamic(a).EntityId))">
            @q.Toolbar
            <a class="faq-question" style="cursor: pointer">
                @q.Question
            </a>
            <div class="faq-answer" style="display: none">@Html.Raw(q.Answer)</div>
        </li>
    }
</ol>

<script src="@App.Path/assets/faq.js" data-enableoptimizations="true"></script>
<script>
	$(document).ready(function() {
		initFaqSection("DnnModule-" + @Dnn.Module.ModuleID, "@Presentation.ShowEffect");
	});
</script>

Look inside

Content Item

These are the values a content-editor can manage.
Name Type Value
Title System.String Demo Selection of Questions Demo Selection of Questions
Introduction System.String Just go into the settings and select existing questions you want to show here. Just go into the settings and select existing questions you want to show here.
Questions ToSic.Eav.Data.EntityRelationship 2550,2554 2550,2554


Presentation Item

These are additional, optional presentation instructions a content-editor can manage. If none are entered, a default set (predefined by the designer) will be used.

No Presentation parameters specified, using default presentation for this item.


Template file

@using ToSic.SexyContent
<h2 class="sc-element">@Content.Title @Content.Toolbar</h2>
<div>@Html.Raw(Content.Introduction)</div>
<ol>
    @foreach (var q in AsDynamic(Content.Questions))
    {
        <li class="sc-element faq-set" data-tags="@String.Join(",", ((List<DynamicEntity>)q.Categories).Select(a => AsDynamic(a).EntityId))">
            @q.Toolbar
            <a class="faq-question" style="cursor: pointer">
                @q.Question
            </a>
            <div class="faq-answer" style="display: none">@Html.Raw(q.Answer)</div>
        </li>
    }
</ol>

<script src="@App.Path/assets/faq.js" data-enableoptimizations="true"></script>
<script>
	$(document).ready(function() {
		initFaqSection("DnnModule-" + @Dnn.Module.ModuleID, "@Presentation.ShowEffect");
	});
</script>
2serve . 2invent . 2create is 2be.