Search code examples
dotnetnuke2sxc

Want to filter by a child Entity in 2scx template


I have a list Entity called Awards which has a Name (string) and YearGiven (Entity) as its fields.

I want to show all awards grouped by Year. ie

2017
---Bob
---Sue
2016
---Fred
2015
etc

Here is my template:

@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 awardsInThisModule = AsDynamic(App.Data["Awards"].List);
        var categoriesUsed = awardsInThisModule.SelectMany(q => ((List<DynamicEntity>)q.YearGiven));

        var distinctCategories = categoriesUsed.Select(AsEntity).Distinct();    // Distinct only works reliably when cast as entity
        sortedCategories = AsDynamic(distinctCategories).OrderBy(q => q.Year);

    }

}
<link rel="stylesheet" href="@App.Path/assets/awards.css" data-enableoptimizations="true" />

@foreach (var cat in sortedCategories)
        {
           <h3> @cat.Year</h3>
             foreach (var q in AsDynamic(App.Data["Awards"].List).Where(t => t.Name == "Bob").OrderBy(q => q.Name))
            {
                //this works fine and puts Bob against each year


                <h2>@q.Name</h2>

            }

           foreach (var q in AsDynamic(App.Data["Awards"].List).Where(t => t.Year.Select(a => AsDynamic(a).Year) == "2017"))
            {
                //this is what I actually want to do and fails
                <h2>@q.Name</h2>

            }



             <br />
        }

I started by changing the Where clause to t.YearGiven == 2016 but that gives an error "Operator '==' cannot be applied to operands of type 'System.Collections.Generic.List' and 'int' a" - I assume because YearGiven is an Entity and so is actually a List<>.
So then I changed to the next foreach in the code and got this error:-
"Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type."

I can't find any template example that does what I'm trying to do and nothing I do works.

N.B. I've hardcoded '2017' in there for now to keep things simple but it will obviously be doing each Year found in the outer loop.


Solution

  • Here is a simple example with a similar schema if you want to adapt it. I am basically using a variable (currCat) to keep track and handle the 'on-change of category'. Hopefully you can ignore all the expando/collapse stuff. Here is what the final looks like: http://www.blackandco.com/Vendor-Linecard

    <div id="vendor-list" role="tablist" class="small">
        @{
            int currCat = 0;
            int firstCo = 851; // Abrasives
            foreach (var aCat in AsDynamic(App.Data["CompanyCategories"])
                    .Where(c => c.CategoryActiveYN == true)
                    .OrderBy(c => c.CategoryName) 
                    )
            {
                currCat = aCat.EntityId;
                <div class="card">
                    <div class="card-header" role="tab" id="@string.Format("{0}{1}", "heading", @currCat)">
                        <h5 class="mb-0@((currCat == firstCo) ? "" : " collapsed")" data-toggle="collapse" href="@string.Format("{0}{1}", "#collapse", @currCat)" 
                            aria-expanded="@((currCat == firstCo) ? "true" : "false")" aria-controls="@string.Format("{0}{1}", "collapse", @currCat)">
                            @aCat.CategoryName
                        </h5>
                    </div>
                    <div id="@string.Format("{0}{1}", "collapse", @currCat)" class="collapse@((currCat==firstCo) ? " show" : "")" role="tabpanel" aria-labelledby="@string.Format("{0}{1}", "heading", @currCat)" data-parent="#accordion" aria-expanded="@((currCat==firstCo) ? "true" : "false")">
                        <div class="card-body">
                            <ul>
                                @foreach (var vComp in AsDynamic(App.Data["Company"])
                            .Where(v => v.CompanyActiveYN && v.IncludeOnVendorCards)
                            .OrderBy(v => v.CompanyName)
                            )
                                {
                                    foreach (var vCat in vComp.CompanyCategory)
                                    {
                                        if (vCat.EntityId == currCat)
                                        {
                                            <li>@vComp.CompanyName<span></li>
                        }
                    }
                                }
                            </ul>
                        </div>
                    </div>
                </div>
            }
        }
    </div>