Term List Order

Feb 25, 2013 at 9:19 PM
Good Afternoon! I have various taxonomies in place, my issue is this:

When I add a new item, I would like it to sort alphabetically. Is there currently no way to do this? Right now I am using the Taxonomies Menu widget and it is a huge mess since it is reading in the order of the taxonomies.
Coordinator
Feb 25, 2013 at 9:43 PM
Right now it's using the Weight property by default.

What you can do to have a custom order is to create a Projection/Query.
Apr 22, 2013 at 12:32 PM
What if I have used a projection to query over terms in a taxonomy (to allow me greater flexibility in formatting the output), and I would like the projection to sort the terms by their weight?

There doesn't seem to be a sort in projections that is based on the taxonomy weight.
Sep 12, 2013 at 10:11 AM
Edited Sep 12, 2013 at 4:12 PM
Re: "There doesn't seem to be a sort in projections that is based on the taxonomy weight."

You could add this (edit: read my following post first).
using System;
using Orchard.Localization;
using Orchard.Projections.Descriptors.SortCriterion;
using Orchard.Projections.Services;
using Orchard.Taxonomies.Models;

namespace Orchard.Taxonomies.Projections
{

    public class TermWeightSortCriterionProvider : ISortCriterionProvider
    {
        public TermWeightSortCriterionProvider()
        {
            T = NullLocalizer.Instance;
        }

        public Localizer T { get; set; }

        public void Describe(DescribeSortCriterionContext describe)
        {
            var descriptor = describe.For("Term Part Properties", T("Term Part Properties"), T("Term Part Weight"));
            descriptor.Element("Weight", T("Weight"), T("Term Part Weight"),
                ApplyFilter,
                DisplaySortCriterion,
                SortDescCriterionFormProvider.FormName
            );
        }

        public void ApplyFilter(SortCriterionContext context)
        {

            bool ascending = Convert.ToBoolean(context.State.Sort);
            context.Query = ascending
                                ? context.Query.OrderBy(alias => alias.Named("termRecord"), x => x.Asc("Weight"))
                                : context.Query.OrderBy(alias => alias.Named("termRecord"), x => x.Desc("Weight"));
        }

        public LocalizedString DisplaySortCriterion(SortCriterionContext context)
        {
            bool ascending = Convert.ToBoolean(context.State.Sort);

            if (ascending) {
                return T("Ordered by {0}, ascending", "Term Part Weight");
            }

            return T("Ordered by {0}, descending", "Term Part Weight");
        }
    }
}
and this (optional - this just makes descending the default sort for weight):
using System;
using Orchard.DisplayManagement;
using Orchard.Forms.Services;
using Orchard.Localization;

namespace Orchard.Projections.Providers.SortCriteria
{
    public class SortDescCriterionFormProvider : IFormProvider
    {

        public const string FormName = "SortOrderDesc";

        protected dynamic Shape { get; set; }
        public Localizer T { get; set; }

        public SortDescCriterionFormProvider(IShapeFactory shapeFactory)
        {
            Shape = shapeFactory;
            T = NullLocalizer.Instance;
        }

        public void Describe(DescribeContext context)
        {
            Func<IShapeFactory, object> form =
                shape =>
                {

                    var f = Shape.Form(
                        _Options: Shape.Fieldset(
                            _ValueFalse: Shape.Radio(
                                Id: "sortDescending", Name: "Sort",
                                Checked: true, // default value
                                Title: T("Sort descending"), Value: "false"
                                ),
                            _ValueTrue: Shape.Radio(
                                Id: "sortAscending", Name: "Sort",
                                Title: T("Sort ascending"), Value: "true"
                                ),
                            Description: T("The direction the field will be sorted by.")
                        ));

                    return f;
                };

            context.Form(FormName, form);

        }
    }

    public class SortCriterionFormValitator : FormHandler
    {
        public Localizer T { get; set; }

        public override void Validating(ValidatingContext context)
        {
            if (context.FormName == SortDescCriterionFormProvider.FormName)
            {
                if (context.ValueProvider.GetValue("Sort") == null)
                {
                    context.ModelState.AddModelError("Sort", T("The Sort field is required.").Text);
                }
            }
        }
    }
}
Sep 12, 2013 at 10:12 AM
Edited Sep 12, 2013 at 5:24 PM
Actually, the above answer is flawed, and over-simplistic.

If you have a single taxonomy attached to the contenttype with just a single level, then yes it will work. Go for it.

Thing is though, most taxonomies are not just ordered by weight, but also by their path, and they have a custom IComparer to do the ordering (Orchard.Taxonomies.Models.Termpart.TermsComparer).

Aside from that, the other issue is you might have 2 or more taxonomies attached to the same content type and want to sort on one of them first, then the other.

All the above would be tricky to implement in a projection query using applyfilter() orchard hql stuff. (Though I'd love to see the code if someone managed all that in the applyfilter method!)

I think you would be better off not using a query/projection, and instead use a standard mvc view/controller in this case, that way you can just write custom code to run your contentmanagerquery + call the IComparer. The obvious downside to this is that without a projection you have to implement your own pager. But that's simple.

Oh, you should also consider - can the contenttype have multiple terms associated with each taxonomy part? If yes, you may want to consider e.g. adding the Compare score together for terms in the same taxonomy part , or giving the first one entered in the taxonomy part more weight priority etc.

So it's not a trivial problem.
Sep 16, 2013 at 7:33 PM
Me too I want to order my query by terms weight. My contenttype have 3 taxonomies and I understood to it not possible to order by weight.
You wrote it is possible to use a standard mvc view/controller... can you give us example please?

Thanks