Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • MB 273 posts 936 karma points
    Sep 05, 2016 @ 13:12
    MB
    1

    Sort nodes by property value (price, textstring)

    So another day, another question. I'm diggin deeper and deeper into Umbraco and learning a lot from both the community and on my own.

    I'm currently working on a little project in Umbraco 7.5.2 where I'd like to show off some products without selling any of them online.

    So it bascially looks like this: Roldskov.sp34k.dk

    The bikes are rendered out like so:

    foreach (var product in categorySection.Children)
                {
                    var imageIds = product.productImages.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
    
                    var images = Umbraco.Media(imageIds);
                    var firstImage = images.FirstOrDefault();
                    var firstImageUrl = firstImage.Url;
                    var firstImageCropUrl = firstImage.GetCropUrl("category image");
    
                    <div class="product">
                        <a href="@product.Url">
                            <img src="@firstImageCropUrl" />
                            <span class="brand">@categorySection.Name</span>
                            <span class="model">@product.Name</span>
                        </a>
                        <div class="price">
                            @product.GetPropertyValue("price") DKK
                        </div>
                    </div>
                }
    

    As you can see, the PRICE is just a textstring, nothing fancy there.

    I would like to be able to sort the bikes by price as you can see in the sidebar where I have a couple of A-tags, none of them works and that's the thing: How do I enable a sorting/filtering feature in Umbraco, based on the price/textstring property?

    Can I see the backend?

    Login removed

  • Alex Skrypnyk 6163 posts 24143 karma points MVP 8x admin c-trib
    Sep 05, 2016 @ 13:30
    Alex Skrypnyk
    1

    Hi Mike,

    You just need to add some get param to each filter, and if request contains this param - filter "categorySection.Children" by this param, it's not hard with LINQ.

    Thanks,

    Alex

  • Frans de Jong 548 posts 1840 karma points MVP 4x c-trib
    Sep 05, 2016 @ 13:40
    Frans de Jong
    1

    There are 2 ways to get the result you want. One is client side filtering with javascript/jquery and the other is serverside.

    If you don't have paging on your productpage I'd opt for the Jquery solution otherwise you will have a page reload every time you click on a price.

    If you want to sort them serverside I would call the same page with a querystring.

    example:

    http://roldskov.sp34k.dk/produkter/cykler/mountain-bikes?pricegroup=0-999
    

    In the view get the value of the querystring:

    string pricegroup = Request.Querystring["pricegroup"]
    

    You can show the bikes fitting the selected pricegroup with a if statement in the foreach.

  • MB 273 posts 936 karma points
    Sep 06, 2016 @ 09:29
    MB
    0

    Hey fellas, Thank you both for joining in on my little (yet epic) adventure to Umbraco's universe ;o)

    Now, this is where I kinda lose track because I'm not that experienced with this kind of programming.

    I do not have pagning on my site but now that I think about it, it might be a good idéa? If I have 100 bikes on one page, it would take a long time to load.

    But since I don't have any paginig, is it possible for me to see an example of how your idéas works? :)

  • Frans de Jong 548 posts 1840 karma points MVP 4x c-trib
    Sep 06, 2016 @ 09:37
    Frans de Jong
    100

    This is a partial view I used in a project.

    What I use here is the tags datatype to define a filter menu. One item can be placed in multiple categories.

    The comment's aren't that detailed but it should get you started.

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    
    @{
        var root = CurrentPage.AncestorOrSelf(1);
        var queryString = HttpUtility.ParseQueryString(Request.QueryString.ToString());
        string selectedCategory = queryString.Get("category");
    
        IEnumerable<IPublishedContent> selection = CurrentPage.Children.Where("visible");
        List<IPublishedContent> selectedItems = new List<IPublishedContent>();
        HashSet<string> CurrentCategories = new HashSet<string> { };
    
        int pageSize = 6;
        int page = 1;
        int.TryParse(queryString.Get("page"), out page);
        int itemCount = selection.Count();
    
    
        @*Get all categories*@
    if (selection != null)
    {
        foreach (var item in selection)
        {
            if (item.HasValue("tags"))
            {
                string tags = item.GetPropertyValue<string>("tags");
                foreach (string tag in tags.Split(','))
                {
                    CurrentCategories.Add(tag);
                }
            }
        }
    }
    
    
    
        @*Render filter*@
    
    if (CurrentCategories.Count != 0)
    {
        string currentClass = "class=active";
        <div class="col-sm-12">
            <ul class="categories">
                <li @(String.IsNullOrEmpty(selectedCategory) ? currentClass : "")>
                    <a href="@CurrentPage.Url@queryStringBuilder("category","")" >All categories</a>
                </li>
    
                @foreach (string category in CurrentCategories)
                {
    
                    <li @(selectedCategory == category ? currentClass : "")>
    
                        <a href="@CurrentPage.Url@queryStringBuilder("category",@category)" >
                            @category
                        </a>
    
                    </li>
                }
            </ul>
        </div>
    }
    
    @*Render items*@
    
    if (!string.IsNullOrEmpty(selectedCategory))
    {
        foreach (IPublishedContent item in selection)
        {
            if (item.HasValue("tags") && ((String.IsNullOrEmpty(item.GetPropertyValue("tags").ToString()) == false) && (Array.IndexOf(item.GetPropertyValue("tags").ToString().Split(','), selectedCategory) >= 0)))
    
            {
                selectedItems.Add(item);
            }
        }
        itemCount = selectedItems.Count();
    
        foreach (var item in selectedItems.Skip((page - 1) * pageSize).Take(pageSize))
        {
            @buildItem(item);
        }
    }
    else if (string.IsNullOrEmpty(selectedCategory))
    {
        foreach (IPublishedContent item in selection.Skip((page - 1) * pageSize).Take(pageSize))
        {
            @buildItem(item);
        }
    }
    
    
    @*===================================
        Pagination
    ===================================*@
    
    int totalPages = (int)Math.Ceiling((double)itemCount / (double)pageSize);
    
    if (page > totalPages)
    {
        page = totalPages;
    }
    else if (page < 1)
    {
        page = 1;
    }
    
    if (totalPages > 1)
    {
        bool previousPageIsEllipsis = false;
        <div class="container">
            <div class="row">
                <div class="col-xs-12 pagination text-center">
                    <ul class="pagination">
                        @if (page > 1)
                    {
                        string newPage = (page - 1).ToString();
                            <li><a href="@CurrentPage.Url@queryStringBuilder("Page",@newPage)">Previous</a></li>
                        }
                        else
                        {
                            string newPage = (page - 1).ToString();
                            <li class="disabled invisible"><a href="@CurrentPage.Url@queryStringBuilder("Page",@newPage)">Previous</a></li>
                        }
                        @for (int p = 1; p < totalPages + 1; p++)
                    {
                        var linkClass = (p == page) ? "active" : "";
                        if (p == page)
                        {
                                <li class="@Html.Raw(linkClass)">
                                    <a href="@CurrentPage.Url@queryStringBuilder("Page",@p.ToString())">@p</a>
                                </li>previousPageIsEllipsis = false;
                        }
                        else
                        {
                            if (p == 1 || p == page - 1 || p == page + 1 || p == totalPages - 1 || p == totalPages)
                            {
                                    <li class="@Html.Raw(linkClass)"><a href="@CurrentPage.Url@queryStringBuilder("Page",@p.ToString())">@p</a></li>
                                    previousPageIsEllipsis = false;
                                }
                                else
                                {
                                    if (previousPageIsEllipsis)
                                    {
                                        continue;
                                    }
                                    else
                                    {
                                        <li><a href="#">...</a></li>
                                        previousPageIsEllipsis = true;
                                    }
                                }
                            }
                        }
                        @if (page < totalPages)
                    {
                        string newPage = (page + 1).ToString();
                            <li class=""><a href="@CurrentPage.Url@queryStringBuilder("Page",@newPage)">Next</a></li>
                        }
                        else
                        {
                            string newPage = (page + 1).ToString();
                            <li class="disabled invisible"><a href="@CurrentPage.Url@queryStringBuilder("Page",@newPage)">Next</a></li>
                        }
                    </ul>
                </div>
            </div>
        </div>
        }
    }
    
    @*===================================
                Helpers
        ===================================*@
    
    @helper buildItem(IPublishedContent item)
    {
        <div class="col-sm-6 project">
            <div class="projectImage">
                @if (!string.IsNullOrEmpty(item.GetPropertyValue("thumbnail").ToString()))
                {
                    IPublishedContent img = Umbraco.Media(item.GetPropertyValue("thumbnail"));
                    <img src="@img.Url" alt="@img.Name" />}
                else
                {
                    <img src="noImg.jpg" />}
    
            </div>
            <div class="projectTitle">
                <a href="@item.Url">@item.Name</a>
            </div>
        </div>
    }
    
    
    @helper queryStringBuilder(string key, string value)
    {
        var queryStringKeyValuePairs = HttpUtility.ParseQueryString(Request.QueryString.ToString());
        string newQueryString = "";
        int counter = 0;
        if (value == "")
        {
            queryStringKeyValuePairs.Remove(key);
        }
        if (value != "")
        {
            queryStringKeyValuePairs.Set(key, value);
        }
    
        foreach (string newKey in queryStringKeyValuePairs)
        {
            if (counter == 0)
            {
                newQueryString += "?" + newKey + "=" + queryStringKeyValuePairs.Get(newKey);
            }
            else
            {
                newQueryString += "&" + newKey + "=" + queryStringKeyValuePairs.Get(newKey);
            }
    
            counter++;
        }
    
        @Html.Raw(newQueryString)
    }
    
  • MB 273 posts 936 karma points
    Sep 07, 2016 @ 12:31
    MB
    0

    Hey Frans,

    Epic share! I salute you Sir (high five)

    I have paging on and it works wonderfully! I really appreciate you for sharing your work with me and the rest of the community. You deserve a cold pint buddy.

  • Frans de Jong 548 posts 1840 karma points MVP 4x c-trib
    Sep 12, 2016 @ 05:25
    Frans de Jong
    0

    No problem,

    I learned from this forum so It's about time I start to contribute.

    Your reply in the email looks different:

    Hey Frans,

    Epic share! I salute you Sir (high five)

    I have created a partial with you're code. I understand SOME of it but not everything.

    So far I have changed all tags with price which works great in the scenario you described. But I wish not to show all prices but sections like Price From: 0 – 999, 1000 – 1999 and so forth.

    How can I transform your Get All Categories foreach to a grouped selection of prices?

    Product image error

    I also seem to have a problem with the buildItem – Thumbnail. I created an Upload property entitled productImage, but it returns this error: Cannot implicitly convert type 'Umbraco.Core.Dynamics.DynamicNull' to 'Umbraco.Core.Models.IPublishedContent'. An explicit conversion exists (are you missing a cast?)

    And thank you!

    I have paging on and it works wonderfully! I really appreciate the share Frans.

    Did you solve these problems?

    Frans

  • Frans de Jong 548 posts 1840 karma points MVP 4x c-trib
    Sep 12, 2016 @ 05:40
    Frans de Jong
    1

    There are a few errors in the code I shared. I'm in the proces of converting all my code to a strongly typed version rather than a dynamic version.

    One mistake is in the buildItem helper.

    @if (!string.IsNullOrEmpty(item.GetPropertyValue("thumbnail").ToString())){}
    

    should be:

    @if (item.HasProperty("thumbnail") && item.HasValue("thumbnail")){}
    

    That solves your error. After that you only need to change thumbnail to your propertyname (productImage).

  • MB 273 posts 936 karma points
    Sep 13, 2016 @ 14:54
    MB
    0

    Hey buddy, Thank you for still sticking around :o)

    A buddy of mine helped me group the prices together, you can see the code below. I just need to check IF there's any products inside each range and display it accordinaly. Not sure how to yet, but I'll try and figure it out :)

    You can see it in action here: http://roldskov.sp34k.dk/produkter/cykler/mountain-bikes/

    Thank you for posting a fix for the images but it renderes this error:

    Cannot implicitly convert type 'Umbraco.Core.Dynamics.DynamicNull' to 'Umbraco.Core.Models.IPublishedContent'. An explicit conversion exists (are you missing a cast?)
    

    COMPLETE CODE (based on Frans de Jong's code

        @inherits Umbraco.Web.Macros.PartialViewMacroPage
    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @{
        var root = CurrentPage.AncestorOrSelf(1);
        var queryString = HttpUtility.ParseQueryString(Request.QueryString.ToString());
        string selectedpriceRange = queryString.Get("priceRange");
        bool isBrandPage = CurrentPage.DocumentTypeAlias == "brandPage";
    
        IEnumerable<IPublishedContent> categories = CurrentPage.Children.Where("visible");
        if (isBrandPage)
        {
            categories = CurrentPage.Parent.Children.Where("visible");
        }
    
        //IEnumerable<IPublishedContent> selectionProducts = CurrentPage.Descendants().Where("visible");
        IEnumerable<IPublishedContent> productTypes = CurrentPage.Descendants().Where("NodeTypeAlias == \"productPage\"");
    
        List<IPublishedContent> selectedItems = new List<IPublishedContent>();
        HashSet<string> CurrentCategories = new HashSet<string> { };
    
        // TODO: Gender virker ikke, skal filtrere ligesom pris blot på gender parameteren
        if (queryString.Get("gender") != null)
        {
            bool isMale = bool.Parse(queryString.Get("gender"));
            selectedItems = selectedItems.Where(x => x.GetPropertyValue<bool>("gender") == isMale).ToList();
        }
    
        int pageSize = 10;
        int page = 1;
        int.TryParse(queryString.Get("page"), out page);
        int itemCount = categories.Count();
    
        @* Get all categories *@
    if (categories != null)
    {
        foreach (var item in productTypes)
        {
            if (item.HasValue("price"))
            {
                string price = item.GetPropertyValue<string>
                    ("price");
                foreach (string tag in price.Split(','))
                {
                    CurrentCategories.Add(tag);
                }
            }
        }
    }
    
        @*Render items*@
        <div id="categoryCollection">
    
            @if (!string.IsNullOrEmpty(selectedpriceRange) && selectedpriceRange.Contains("-"))
            {
                string[] priceArray = selectedpriceRange.Split('-');
                int minPrice = 0;
                int maxPrice = 0;
                if (priceArray.Count() == 2 && int.TryParse(priceArray[0], out minPrice) && int.TryParse(priceArray[1], out maxPrice))
                {
                    selectedItems.AddRange(productTypes
                        .Where(x => x.HasValue("price") &&
                        x.GetPropertyValue<int>("price") > minPrice &&
                        x.GetPropertyValue<int>("price") < maxPrice)
                        .Skip((page - 1) * pageSize).Take(pageSize));
                    foreach (var item in selectedItems)
                    {
                        @buildItemProduct(item);
                    }
                }
            }
            @*else
                {
                    foreach (IPublishedContent item in productTypes.Skip((page - 1) * pageSize).Take(pageSize))
                    {
                        @buildItemProduct(item)
                    }
                }*@
        </div>
    
        @*Render filter*@
        <div id="sidebar">
            <div class="subtitle">
                Mærker
            </div>
            <nav id="subMenu" class="section">
                <ul>
                    @foreach (IPublishedContent item in categories)
                {
                        <li>
                            @buildItem(item)
                        </li>
                    }
                </ul>
            </nav>
    
            @if (CurrentCategories.Count != 0)
            {
                string currentClass = "class=active";
                <div class="subtitle">
                    Priser fra
                </div>
                <ul id="priceFilter" class="section">
                    <li @(String.IsNullOrEmpty(selectedpriceRange) ? currentClass : "")>
                        <a href="@CurrentPage.Url@queryStringBuilder("priceRange", "")">Alle priser</a>
                    </li>
                    @{  var priceRanges = new Dictionary<int, int>();
                        priceRanges.Add(0, 4999);
                        priceRanges.Add(5000, 9999);
                        priceRanges.Add(10000, 14999);
                        priceRanges.Add(15000, 24999);
                        priceRanges.Add(25000, 34999);
                        priceRanges.Add(35000, 44999);
                        priceRanges.Add(45000, 54999);
                        priceRanges.Add(55000, 95000);
                    }
                    @foreach (KeyValuePair<int, int> range in priceRanges)
                    {
                        <li>
                            <a href="@CurrentPage.Url@queryStringBuilder("priceRange", string.Format("{0}-{1}", range.Key, range.Value))">
                                @string.Format("{0} - {1}", range.Key, range.Value)
                            </a>
                        </li>
                    }
                </ul>
                <div class="subtitle">
                    køn
                </div>
                <ul>
                    <li> <a href="@CurrentPage.Url@queryStringBuilder("gender", "true")">Mand</a></li>
                    <li> <a href="@CurrentPage.Url@queryStringBuilder("gender", "false")">Kvinde</a></li>
                </ul>
                        }
        </div>
    
        @*===================================
                Pagination
            ===================================*@
    int totalPages = (int)Math.Ceiling((double)itemCount / (double)pageSize);
    
    if (page > totalPages)
    {
        page = totalPages;
    }
    else if (page < 1)
    {
        page = 1;
    }
    
    if (totalPages > 1)
    {
        bool previousPageIsEllipsis = false;
        <div class="container">
            <div class="row">
                <div class="pagination text-center">
                    <ul class="pagination">
                        @if (page > 1)
                        {
                            string newPage = (page - 1).ToString();
                            <li><a href="@CurrentPage.Url@queryStringBuilder("Page", @newPage)"> Previous </a></li>
                        }
                        else
                        {
                            string newPage = (page - 1).ToString();
                            <li class="disabled invisible"><a href="@CurrentPage.Url@queryStringBuilder("Page",@newPage)">Previous</a></li>
                        }
                        @for (int p = 1; p < totalPages + 1; p++)
                        {
                            var linkClass = (p == page) ? "active" : "";
                            if (p == page)
                            {
                                <li class="@Html.Raw(linkClass)">
                                    <a href="@CurrentPage.Url@queryStringBuilder("Page",@p.ToString())">@p</a>
                                </li>previousPageIsEllipsis = false;
                            }
                            else
                            {
                                if (p == 1 || p == page - 1 || p == page + 1 || p == totalPages - 1 || p == totalPages)
                                {
                                    <li class="@Html.Raw(linkClass)"><a href="@CurrentPage.Url@queryStringBuilder("Page",@p.ToString())">@p</a></li>
                                    previousPageIsEllipsis = false;
                                }
                                else
                                {
                                    if (previousPageIsEllipsis)
                                    {
                                        continue;
                                    }
                                    else
                                    {
                                        <li>
                                            <a href="#">
                                            </a>
                                        </li>
                                        previousPageIsEllipsis = true;
                                    }
                                }
                            }
                        }
                        @if (page < totalPages)
                        {
                            string newPage = (page + 1).ToString();
                            <li class="">
                                <a href="@CurrentPage.Url@queryStringBuilder("Page",@newPage)">Next</a>
                            </li>
                        }
                        else
                        {
                            string newPage = (page + 1).ToString();
                            <li class="disabled invisible"><a href="@CurrentPage.Url@queryStringBuilder("Page",@newPage)">Next</a></li>
                        }
                    </ul>
                </div>
            </div>
        </div>
                        }}
    
    @*===================================
                Helpers
        ===================================*@
    @helper buildItemProduct(IPublishedContent item)
    {
    
        <div class="product">
    
    
            <a href="@item.Url">
              @if (item.HasProperty("productImage") && item.HasValue("productImage")) 
                  {
                      IPublishedContent img = Umbraco.Media(item.GetPropertyValue("productImage"));
                    <img src="@img.Url" alt="@img.Name" />
                  }
                else
                {
                    <img src="noImg.jpg" />
                }
    
                <span class="brand">@item.Parent.Name</span>
                <span class="model">@item.Name</span>
            </a>
            <div class="price">
                @item.GetPropertyValue("price") DKK
            </div>
        </div>
    }
    
    @helper buildItem(IPublishedContent item)
    {
    string currentClass = "class=active";
        <li @(CurrentPage.Name == item.Name ? currentClass : "")>
            <a href="@item.Url">@item.Name</a>
            <a href="@CurrentPage.Parent.Url" @(CurrentPage.Name == item.Name ? currentClass : "class=hide")><i class="fa fa-close"></i></a>
        </li>
    }
    
    @helper queryStringBuilder(string key, string value)
            {
    var queryStringKeyValuePairs = HttpUtility.ParseQueryString(Request.QueryString.ToString());
    string newQueryString = "";
    int counter = 0;
    if (value == "")
    {
        queryStringKeyValuePairs.Remove(key);
    }
    if (value != "")
    {
        queryStringKeyValuePairs.Set(key, value);
    }
    
    foreach (string newKey in queryStringKeyValuePairs)
    {
        if (counter == 0)
        {
            newQueryString += "?" + newKey + "=" + queryStringKeyValuePairs.Get(newKey);
        }
        else
        {
            newQueryString += "&" + newKey + "=" + queryStringKeyValuePairs.Get(newKey);
        }
    
        counter++;
    }
    
        @Html.Raw(newQueryString)
    }
    
Please Sign in or register to post replies

Write your reply to:

Draft