简体   繁体   中英

2sxc | Add second filter by entity dropdown to template app

I am trying to add another filter to the FAQ Categories>Questions w/ Filter App and have bascially duplicated the working code for the first filter but it isn't working even though I have setup a second entity type just like the first filter. See sample code below.

My cshtml code:

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

    IEnumerable<dynamic> sortedTypes;

    // 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(App.Data["CO-Filter"].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);

    var typesInThisModule = AsDynamic(App.Data["CO-Filter"].List);
    var typesUsed = typesInThisModule.SelectMany(a => ((List<DynamicEntity>)a.Types));
    var distinctTypes = typesUsed.Select(AsEntity).Distinct();    // Distinct only works reliably when cast as entity
    sortedTypes = AsDynamic(distinctTypes).OrderBy(a => a.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.Title</option>
        }
    </select>
</div>
<div>
    <strong>@App.Resources.FilterBy </strong>
    <select id="ddlFeatureFilterOne">
        <option value="allOne">@App.Resources.ShowAll</option>
        @foreach (var catOne in sortedTypes)
        {
        <option value="@catOne.EntityId">@catOne.Title</option>
        }
    </select>
</div>
<ol>
    @foreach (var q in AsDynamic(App.Data["CO-Filter"]))
    {
    <li class="sc-element faq-set faq-setOne" data-tags="@String.Join(",", ((List<DynamicEntity>)q.Categories).Select(a => AsDynamic(a).EntityId))">
        @q.Toolbar @Edit.Toolbar(actions: "edit,new", contentType: "CO-Filter")
        <a class="faq-question" style="cursor: pointer">
            @if(!String.IsNullOrEmpty(q.LinkText))
            {
            @q.LinkText
            } else {
            @q.Link
            }
        </a>
    </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>

My updated assets/faq js code:

function initFaqSection(containerSelector, showEffect) {
    var container = $("." + containerSelector);
    $(".faq-question", container).click(function (e) {
        var answer;
        switch(showEffect) {
            case "slide":
                answer = $(e.target).closest(".faq-set").find(".faq-answer");
                answer.slideToggle();
                e.preventDefault();
                break;
            case "lightbox":
                var question = $(e.target);
                answer = question.next();
                answer.dialog({
                    title: question.text(),
                    autoOpen: true,
                    dialogClass: "dnnFormPopup",
                    modal: true
                });
            default:
                break;
        }
    });

    // Attach drop-down filter
    $("#ddlFeatureFilter", container).change(function (changeEvent) {
        var tagFilter = changeEvent.target[changeEvent.target.selectedIndex].value;
        console.log("tf:" + tagFilter);
        //alert(tagFilter);
        $(".faq-set", container).each(function (i, e) {
            var tags = ($(e).attr('data-tags') + ",all").split(',');
            console.log(tags);
            if ($.inArray(tagFilter, tags) != -1)// || tagFilter == "all")
                $(e).slideDown();
            else
                $(e).slideUp();
        });
    });

        // Attach drop-down filter
    $("#ddlFeatureFilterOne", container).change(function (changeEvent) {
        var tagFilter = changeEvent.target[changeEvent.target.selectedIndex].value;
        console.log("tf:" + tagFilter);
        //alert(tagFilter);
        $(".faq-set", container).each(function (i, e) {
            var tags = ($(e).attr('data-tags') + ",allOne").split(',');
            console.log(tags);
            if ($.inArray(tagFilter, tags) != -1)// || tagFilter == "allOne")
                $(e).slideDown();
            else
                $(e).slideUp();
        });
    });

}

The content item entity fields setup: 在此处输入图片说明

The content item itself:

在此处输入图片说明

What I currently have (note second filter only displays but doesnt filter by 'type').

在此处输入图片说明

I know my code is incorrect but is there an easy solution?

Also, is there any easy way if a link is displayed (no linktext entered by a user) to remove the path url and the extension?

Thx

UPDATE:

I have tried to create a combined function like so:

function initFaqSection(containerSelector, showEffect) {
    var container = $("." + containerSelector);
    $(".faq-question", container).click(function (e) {
        var answer;
        switch(showEffect) {
            case "slide":
                answer = $(e.target).closest(".faq-set").find(".faq-answer");
                answer.slideToggle();
                e.preventDefault();
                break;
            case "lightbox":
                var question = $(e.target);
                answer = question.next();
                answer.dialog({
                    title: question.text(),
                    autoOpen: true,
                    dialogClass: "dnnFormPopup",
                    modal: true
                });
            default:
                break;
        }
    });
    // Attach drop-down filters
    function runFilters() { 
        var filter1 = $("#ddlFeatureFilterOne").value;
        var filter2 = $("#ddlFeatureFilterTwo").value;
        //alert(filters);
        $("#ddlFeatureFilterTwo", container).change(runFilters);
            $(".faq-set", container).each(function (i, e) {
            var tags = ($(e).attr('data-tags') + ",allTwo").split(',');
            console.log(tags);
            if ($.inArray(filter1, tags) != -1 && $.inArray(filter2, tags) != -1)
                $(e).slideDown();
            else
                $(e).slideUp();
            });
    }
}

with my cshtml code as follows:

<div>
    <strong>@App.Resources.FilterBy </strong>
    <select id="ddlFeatureFilterOne">
        <option value="allTwo">@App.Resources.ShowAll</option>
        @foreach (var catOne in sortedCategories)
        {
        <option value="@catOne.EntityId">@catOne.Name</option>
        }
    </select>
    <select id="ddlFeatureFilterTwo">
        <option value="allTwo">@App.Resources.ShowAll</option>
        @foreach (var catTwo in sortedTypes)
        {
        <option value="@catTwo.EntityId">@catTwo.Name</option>
        }
    </select>
</div>

but this still only works the first filter?

So just as a side-note: you're asking a sequence of different questions in one issue, which makes it harder to answer. I recommend you split the questions in the future.

Now the problem you're having is the fact that you have two filters which currently don't know anything about each other. So the real solution is

  1. to have a combined runFilters() method which takes the value from both dropdowns and applies both
  2. your binding should then only call this, like $("#ddlFeatureFilterOne", container).change(runFilters);

The runFilters will look something like this (pseodo code):

``` function runFilters() { var filter1 = $("#ddl...").value; // not sure if it's .value var filter2 = $("#...")...;

    $(".faq-set", container).each(function (i, e) {
        var tags = ($(e).attr('data-tags') + ",allOne").split(',');
        console.log(tags);
        if ($.inArray(filter1, tags) != -1 && $.inArray(filter2, tags) != -1)
            $(e).slideDown();
        else
            $(e).slideUp();
    });

}

```

something like that :). for removing the path, you want to trim it in JS by the lastIndexOf("/") - see https://www.w3schools.com/JSREF/jsref_lastindexof.asp or using the c# equivalent https://msdn.microsoft.com/en-us/library/system.string.lastindexof(v=vs.110).aspx

I found a solution in the end....

It required me to add a 'data-title' tag as otherwise I could not link the data connected w/ filter1 (Categories) w/ that of filter2 (Types):

data-title="@String.Join(",", ((List<DynamicEntity>)q.Categories).Select(a => AsDynamic(a).EntityId))"

So I associated 'data-title' w/ my Categories filter and associated 'data-tags' w/ my Types filter.

My cshtml filter code:

<div>
    <strong>@App.Resources.FilterBy </strong>
    <select id="ddlFeatureFilterOne">
        <option value="allTwo">@App.Resources.ShowAll</option>
        @foreach (var catOne in sortedCategories)
        {
        <option value="@catOne.EntityId">@catOne.Name</option>
        }
    </select>
    <select id="ddlFeatureFilterTwo">
        <option value="allTwo">@App.Resources.ShowAll</option>
        @foreach (var catTwo in sortedCategoriesTypes)
        {
        <option value="@catTwo.EntityId">@catTwo.Name</option>
        }
    </select>
</div>
<ol>
    @functions{
        public static string SplitWord(string text)
        {
            int slash = text.LastIndexOf("/");
            int dot = text.LastIndexOf(".");
            dot--;
            var data = text.Substring(slash + 1, dot - slash);
            return data;
        }
    }
            @foreach (var q in AsDynamic(App.Data["CatFilter"]))
        {
                <li class="sc-element faq-set" data-title="@String.Join(",", ((List<DynamicEntity>)q.Categories).Select(a => AsDynamic(a).EntityId))" data-tags="@String.Join(",", ((List<DynamicEntity>)q.Types).Select(a => AsDynamic(a).EntityId))">
                    @q.Toolbar @Edit.Toolbar(actions: "edit,new,more", contentType: "CatFilter")
                    <a class="faq-question" href="@q.Link" style="cursor: pointer">
                        @if (!String.IsNullOrEmpty(q.LinkText))
                    {
                            @q.LinkText
                    }
                    else
                    {
                            @SplitWord(q.Link);
                    }
                    </a>
                </li>
        }
</ol>

And my adjusted runFilters function code:

    function runFilters() { 
    var filter1 = $("#ddlFeatureFilterOne").value;
    var filter2 = $("#ddlFeatureFilterTwo").value;
    }
    //alert(tagFilter);
    $("#ddlFeatureFilterOne", container).change(function(){
        var filter1 = $("#ddlFeatureFilterOne").val();
        var filter2 = $("#ddlFeatureFilterTwo").val();
        $(".faq-set", container).each(function (i, e) {
            var title = ($(e).attr('data-title') + ",allTwo").split(',');
            var tags = ($(e).attr('data-tags') + ",allTwo").split(',');
            console.log(title);
            if ($.inArray(filter1, title) != -1 && $.inArray(filter2, tags) != -1)
            $(e).slideDown();
        else
            $(e).slideUp();
        });
    });
    $("#ddlFeatureFilterTwo", container).change(function () {
        var filter1 = $("#ddlFeatureFilterOne").val();
        var filter2 = $("#ddlFeatureFilterTwo").val();
        $(".faq-set", container).each(function (i, e) {
            var tags = ($(e).attr('data-tags') + ",allTwo").split(',');
            var title = ($(e).attr('data-title') + ",allTwo").split(',');
            console.log(tags);
            if ($.inArray(filter1, title) != -1 && $.inArray(filter2, tags) != -1)
                $(e).slideDown();
            else
                $(e).slideUp();
        });
    });

Hope this helps others w/ similar issues

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM