Table of Contents

Sorting OrderLines

How to sort OrderLines using the OrderTemplateExtender

When a cart template is rendered, the OrderLines are rendered through a GetLoop() iteration. Sorting of OrderLines goes fairly easy as long as you have actual fields on the OrderLine you can use for SortBy functionality. But if the sorting needs to be more complex, based on a set of rules, sorting becomes more of a hassle as there is no actual collection of OrderLine objects available. This is where the OrderTemplateExtender comes in handy.

OrderTemplateExtender

With the introduction of Razor (cshtml), the use of TemplateExtenders has been quite diminished. These extenders gives us the possibility to tamper the content before rendering, which made more sense back when templates were HTML, and less so now with Razor.

But in this particular scenario, the OrderTemplateExtender is of good use, as it holds the entire Order object, including OrderLines. The OrderTemplateExtender has two TemplateExtenderRenderingState: Before and After. Hooking up on the TemplateExtenderRenderingState.Before, we can now manipulate the order and OrderLines before rendering.

The scenario

In the example below we have some OrderLines with information of ParentLineId saved to custom OrderlineField, to indicate that they belong to a parent line. Had the OrderLines with a value in ParentLineId been of type 'ProductDiscount'/'Discount', the Dynamicweb API would have given us the functionality of nesting child-lines under parent lines: for free and automatically. Now we need to handle the sorting on our own:

using Dynamicweb.Ecommerce.Frontend;
using Dynamicweb.Ecommerce.Orders;
using Dynamicweb.Rendering;
using System.Collections.Generic;
using System.Linq;

namespace MyNamespace
{
    /// <summary>
    /// Ensure that all lines with a value in ParentLineId are nested under their respective parents.
    /// </summary>
    public class OrderTemplateExtender1 : OrderTemplateExtender
    {
        public override void ExtendTemplate(Template template)
        {
            if (RenderingState == TemplateExtenderRenderingState.Before)
            {
                var orderLineList = Order.OrderLines.ToList();

                // Get list of sorted OrderLines to have children nested under their respective parent.
                var sortedOrderLines = OrderlinesSorted(orderLineList);

                // Clear current orderlines from the order.
                Order.OrderLines.Clear();

                // Apply the sorted orderlines.
                foreach (var orderLine in sortedOrderLines)
                {
                    Order.OrderLines.Add(orderLine);
                }
            }
        }

        /// <summary>
        /// Returns a List of sorted OrderLines
        /// </summary>
        /// <param name="orderLines"></param>
        /// <returns>List<OrderLines></returns>
        private List<OrderLine> OrderlinesSorted(List<OrderLine> orderLines)
        {
            List<OrderLine> parents = new List<OrderLine>();
            List<OrderLine> children = new List<OrderLine>();
            List<OrderLine> sorted = new List<OrderLine>();

            // Split OrderLines into...
            foreach (var line in orderLines)
            {
                var parentId = line.GetOrderLineFieldValue("ParentLineId")?.Value;
                if (string.IsNullOrEmpty(parentId))
                {
                    // ..parents
                    parents.Add(line);
                }
                else
                {
                    // ..and children
                    children.Add(line);
                }
            }

            // Place children just after their respective parent
            foreach (var parent in parents)
            {
                // Add each parent
                sorted.Add(parent);

                foreach (var child in children)
                {
                    var parentId = child.GetOrderLineFieldValue("ParentLineId").Value;
                    if (parentId == parent.Id)
                    {
                        // For each parent, add related children
                        sorted.Add(child);
                    }
                }
            }
            return sorted;
        }
    }
}
To top