I've got a checkboxlist datatype (let's call it categories). An editor can select multiple categories, obviously. When I render the categories in a view, they don't retain the sort order I have assigned in the data type editor. I can see the sort order is there in the DB.
How can I force them to sort using the sort order?
Somewhat tangential to this, can I have a checkboxlist save with something other than a comma as a delimiter? I have commas in my categories (e.g, "foo, bar and baz" is what a category might look like). That comma in there means I can't split on comma like I normally would.
Actually, no, I'm not doing that. Now that you put it like this it's immediately clear what the problem is. I'm gathering categories for a number of nodes from an Examine index. I'm iterating through the nodes in the index, grabbing the categories for each and adding to a list. I then deduplicate and tidy the list to give me a list of all categories that apply to the nodes in the index. I see now, of course, there is no sort order stored in the index. Even if there were, I'm not handling a sort order in any way. Blindingly obvious now that I see it. :)
So how else could I approach this?
Grab the sort order somehow and store it in the index alongside the categories?
Get the sort order after I've retrieved my list of categories?
Something else?
Here's the code to illustrate:
// Create a List of categories
var categories = new List<string>();
foreach (var publication in searchResults)
{
if (publication.Fields.ContainsKey("category2"))
{
string[] splitCategories = publication.Fields["category2"].Split(',');
categories.AddRange(splitCategories);
}
}
// Dedupe and trim categories
categories = categories.Distinct().Select(c => c.Trim()).ToList();
An interesting one - I can only think of hacky ways of doing this!
Is the list of the categories likely to change or could you hardcode a list into this code and mark which ones to output? If it will change you'd have to do a call to the DataTypeService each time (which I think will hit the DB?).
I was then going to suggest you could use Intersect to only output the items in the sorted list also in the list returned in your logic above but I think the sort order would be lost again as Intersect doesn't preserve the order.
The really hacky, but much simplier, way of doing this would be to prefix the values with an integer e.g.
1 | Some Category
2 | Some other category
Then sort the list and strip the number (up to and including the pipe) on output.. your editors would see this number in the back office I guess which is a bit ugly.
Wonder if anyone has any better suggestions out there?
I've no problem with a hacky pragmatic solution. :)
I don't think the categories will change much if at all, so a hard-coded solution is worth contemplating. The spec is for the editor to be able to re-arrange the order of the categories and perhaps add/edit categories. They have access to the data type editor so they can add, delete and sort categories for themselves.
In real terms, I'm not sure how often they're really going to do this, so it may just be better to hard-code it.
I've no idea about using the DataType Service - I've not done that before.
All of the categories are going to be used, come to think of it, so I can query out all of them like this:
var db = ApplicationContext.Current.DatabaseContext.Database;
var categories = db.Fetch<string>(new Sql()
.Select("value")
.From("cmsDataTypePreValues")
.Where("datatypeNodeId = '71312'")
.OrderBy("sortorder"));
Is that really nasty? It's only a tiny query, but hitting the database like this can't be much good can it? This stuff is in a partial so I can cache it. Would doing this be mitigation enough? It's not a highly trafficked page anyway.
If this really is an ill-advised approach, I think I'll go with your numbered prefixes idea. That approach did cross my mind actually, so it's good to know others might do it like this too.
Well if it works and you're throwing caching at it who am I to criticise :)
Here's a cut down working example using the DataTypeService - is it better than your method... no idea!
var dts = ApplicationContext.Current.Services.DataTypeService;
// get all categories in sorted order from DataTypeService
List<string> categoryAllValues = dts.GetPreValuesByDataTypeId(1123).ToList();
}
@{
if (Model.Content.HasValue("categories"))
{
List<string> categories = Model.Content.GetPropertyValue<string>("categories").Split(',').ToList<string>();
<ul>
@* loop through each category *@
@foreach (var curCategory in categoryAllValues)
{
@* only output if it's in the content *@
if (categories.Contains(curCategory))
{
<li>@curCategory</li>
}
}
</ul>
}
}
Ah, no, spoke too soon. GetPreValuesByDataTypeId() doesn't use the sort order. It returns the pre-values in the order they appear in the database. Might make a nice contribution to have it optionally make use of the sort order. I had a look at the code in core to see if it would be easy, but it's beyond me at the moment.
Sorting checkboxlist items in a view
I've got a checkboxlist datatype (let's call it categories). An editor can select multiple categories, obviously. When I render the categories in a view, they don't retain the sort order I have assigned in the data type editor. I can see the sort order is there in the DB.
How can I force them to sort using the sort order?
Somewhat tangential to this, can I have a checkboxlist save with something other than a comma as a delimiter? I have commas in my categories (e.g, "foo, bar and baz" is what a category might look like). That comma in there means I can't split on comma like I normally would.
Many thanks!
Hi Charles!
How are you rendering the values?
I've just done the following:
And the order matched what I had modified in the data type?
}
Are you doing anything different to the above?
Steve
Hi Steve - good to hear from you!
Actually, no, I'm not doing that. Now that you put it like this it's immediately clear what the problem is. I'm gathering categories for a number of nodes from an Examine index. I'm iterating through the nodes in the index, grabbing the categories for each and adding to a list. I then deduplicate and tidy the list to give me a list of all categories that apply to the nodes in the index. I see now, of course, there is no sort order stored in the index. Even if there were, I'm not handling a sort order in any way. Blindingly obvious now that I see it. :)
So how else could I approach this?
Grab the sort order somehow and store it in the index alongside the categories?
Get the sort order after I've retrieved my list of categories?
Something else?
Here's the code to illustrate:
An interesting one - I can only think of hacky ways of doing this!
Is the list of the categories likely to change or could you hardcode a list into this code and mark which ones to output? If it will change you'd have to do a call to the DataTypeService each time (which I think will hit the DB?).
I was then going to suggest you could use Intersect to only output the items in the sorted list also in the list returned in your logic above but I think the sort order would be lost again as Intersect doesn't preserve the order.
The really hacky, but much simplier, way of doing this would be to prefix the values with an integer e.g.
Then sort the list and strip the number (up to and including the pipe) on output.. your editors would see this number in the back office I guess which is a bit ugly.
Wonder if anyone has any better suggestions out there?
HTH
Steve
I've no problem with a
hackypragmatic solution. :)I don't think the categories will change much if at all, so a hard-coded solution is worth contemplating. The spec is for the editor to be able to re-arrange the order of the categories and perhaps add/edit categories. They have access to the data type editor so they can add, delete and sort categories for themselves.
In real terms, I'm not sure how often they're really going to do this, so it may just be better to hard-code it.
I've no idea about using the DataType Service - I've not done that before.
All of the categories are going to be used, come to think of it, so I can query out all of them like this:
Is that really nasty? It's only a tiny query, but hitting the database like this can't be much good can it? This stuff is in a partial so I can cache it. Would doing this be mitigation enough? It's not a highly trafficked page anyway.
If this really is an ill-advised approach, I think I'll go with your numbered prefixes idea. That approach did cross my mind actually, so it's good to know others might do it like this too.
Any other suggestions still welcome!
Cheers, Charles
Well if it works and you're throwing caching at it who am I to criticise :)
Here's a cut down working example using the DataTypeService - is it better than your method... no idea!
Nice one thanks. Using the DataTypeService looks like the way to do it to me. Nice to know there are plenty of options either way.
Thanks, Steve, much appreciated.
Ah, no, spoke too soon.
GetPreValuesByDataTypeId()
doesn't use the sort order. It returns the pre-values in the order they appear in the database. Might make a nice contribution to have it optionally make use of the sort order. I had a look at the code in core to see if it would be easy, but it's beyond me at the moment.So back to using the PetaPoco query for now.
Hi,
What do you mean by the sort order - as in the order the items are in the backoffice -> Developer -> Data types?
I've just tested this and it works - what version of Umbraco are you using?
Steve
I realise that those pictures alone prove nothing so here is the changed order:
Version 6, so I am guessing this has been fixed in 7.
is working on a reply...