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 6182 posts 24283 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 550 posts 1862 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 550 posts 1862 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 550 posts 1862 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 550 posts 1862 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)
    }
    
  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies