Storing SelectMany as IList rather than comma seperated string - episerver

I have an episerver block with one of the property being SelectMany as below
[SelectMany(SelectionFactoryType = typeof(ItemSelectionFactory))]
public virtual string Countries { get; set; }
Since this is a multiselect ,the default type for this is string which is stores the values as comma separated string.
What I am looking for is a way to store it in a list rather than string.
I came across an article to get an IList rather than string but I couldn't find property named valueIsCsv. I am working in Episerver 11 version & not sure if this property is available in a lower version but its definitely not in 11 or am I missing something here.
https://www.epinova.no/en/folg-med/blog/2019/enabling-out-of-the-box-editing-with-the-selectmany-attribute-for-a-ilist-of-contentreferences/
Is there a way to store the data in IList rather than string that is comma seperated.
Any help is appreciated.
Regards.

Related

How to get CheckBoxList values in Umbraco using ContentService

Anyone knows how to get list of selected CheckBoxList values from Umbraco using ContentService?
I use contentService.GetValue("currencies")
and I get string with numbers and commas something like "154,155,156,157"
How can I get actual values?
Does anyone know how to do it using DataTypeService?
As it was mentioned above, you can use Umbraco helpers method to retrieve string value for the PreValue id.
Umbraco.GetPreValueAsString([PreValueId])
You can find more about it here: https://our.umbraco.org/documentation/reference/querying/umbracohelper/#getprevalueasstring-int-prevalueid
It's calling database directly through the DataTypeService behind the scene. It's worth to reconsider it and close it on another type of property / data type to avoid calling database on the frontend layer and just retrieve data from IPublishedContent cached model.
Read also about common pitfalls and anti-patterns in Umbraco: https://our.umbraco.org/documentation/Reference/Common-Pitfalls/
Those are prevalues.
From that given string, you have to split those and get the real value by calling one of umbraco library umbraco.library.GetPreValueAsString(123);
For example.
foreach(var item in contentService.GetValue("currencies").Split(',')) {
var realValue = umbraco.library.GetPreValueAsString(int.Parse(item);
}
You have 2 nulls because prevalues sometimes has blank values on it, like "121,56,,15,145".
You need then to modify your split code like this
foreach (var item in value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
}
StringSplitOptions.RemoveEmptyEntries will ignore empty spaces.

Querying database in Grails

The values in database are saved as such
::{"rating1":"2","rating2":"4","rating3":"5","rating4":"0","rating5":"0"},
Now I need to acces the individual values like 2,4,5 etc.
I made a variable "rating" of the Domain Class type and tried accesing as object using (.) operator but it wont work and gives error:
:exception::groovy.lang.MissingPropertyException: No such property: rating1 for class: java.lang.String
, I tried casting to array and list (as Array, as ArrayList, as List) etc but that wont work either.
Casting to List gives exception:exception::org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '{"rating1":"2","rating2":"4","rating3":"5","rating4":"0","rating5":"0"}' with class 'java.lang.String' to class 'java.util.List' .
Accessing like "rating[3]" gives answer "a". Should I use "rating[11]" to get value 2 or is there any way around.
What could be the possible solution. Please help.
You're storing a string, so you only have string operations available. You need to parse that string to get at the attributes individually (JsonSlurper perhaps?).
rating[character-position] is a bad idea IMO.
Maybe transients (check the GORM docs) would be useful.
class YourDomain {
String yourField
String getRating1() { new JsonSlurper().parseText(yourField).rating1 }
}
Maybe. Totally untested, just an idea.

using array of array of list of lists? C#

Im not an IT guy and trying some programming in his spare time and was wondering how to tackle following issue. It must be very very simple but can`t figure it out, even after dozen of read articles on stackoverflow.
I have a series of values which I need to put in a list or array which goes in another array or list. Like this:
Series one:
"name","Madman"
"dateOfBirth", 11/03/1990 //which is a DateTime object.
"hobby","chopping up family members"
Series two
"name","Dad"
"dateOfBirth", 11/03/1965 //which is a DateTime object.
"hobby","biking"
Series one and two go in another list like this:
allSeries: Series one, Series two
Any ideas? Thanks very much!
Create a class (possibly named Person) that has attributes name, dateOfBirth, and hobby (this encapsulates the data). Set the data through a constructor or setter methods. Then store the instances of Person into a list, or array, or whatever you choose - probably called people. Example: List<Person> people = new List<Person>();.
In your original approach you would have had to have declared your storage data structure as a more generic type. A nice bonus of this approach is that you know the types of the data stored in the class.
so depending on the language you are using you would make another list/array and make an array of arrays (or array of lists). Which language are you using? in Java you would make a List<List<String>> object for example and add things like this. Hope this is a start.
Edit: for c# see: http://www.dotnetperls.com/nested-list
I would do this: create a class containing your attributes, then place multiple instances in a list.
public class Person
{
public string name {get;set;}
public Date dateOfBirth {get; set;}
public string hobby {get;set;}
}
And place them in a list like so: {person1; person2,...}

Bind to specific item in collection without indexer

I am using an EF5 datamodel, in which the related entities are collected into a HashSet. I want to bind an element to the first related entity in the HashSet. I've seen answers on SO (here and here) which suggest using the following:
<DataGridComboBoxColumn SelectedValueBinding="{Binding LeadSteps[0].NewZoneID}"/>
but this relies on the collection having an indexer, which HashSet doesn't have.
(If this cannot be done, I can create a property in a partial class to the entity, and bind to that.)
How can I bind to the n-th item in a collection when the collection doesn't implement an integral indexer?
I know it's an old question, but i also ran into just the same problem and found a solution i thought to share.
What worked for me was changing the declaration of the referencing member from:
public virtual ICollection<MyType> MyVarName { get; set; }
to:
public virtual IList<MyType> MyVarName { get; set; }
After this change, the collection items were accessible with the normal accessor:
<TextBlock Text="{Binding MyVarName[0].MyMemberName}" />
You might need to rethink this whole situation. A HashSet is a 'set' of unique items, not a collection. A set is simply meant to maintain a group of members and to enable you to check whether a particular item is a member or not... there's no indexing because there is no order amongst the set items.
Although you can call the Enumerable.ElementAt<TSource> method on a HashSet, you cannot guarantee that it will return the same element when providing the same input value to the method. Most importantly, if the order of items in the HashSet is important to you, then you should be using a collection instead.
However, if you choose to ignore this advise, this is how you could achieve your requirement... just define a wrapper property for your single HashSet value... you could try something like this:
public YourHashSetDataType Hash
{
get { return LeadSteps.ElementAt(0).NewZoneID; }
set { LeadSteps.ElementAt(0).NewZoneID = value; NotifyPropertyChanged("Hash"); }
}

How to assignTo a setter in Salesforce that requires an index parameter, such as a List<>?

In a controller I have two values:
public List<String> StringValue {get; set;}
public List<String> ListValue {get; set;}
The ListValue is initialized in the constructor and several strings are added. At this point in a value I can refer to these with {!StringValue} and {!ListValue[1]} in a VisualForce page. The list one in particular is the focus - I can even add pseudo-constants (getters) as indexes, making {!ListValue[nameIndex]} a valid reference.
However I've run into an exception when trying to set a list value instead of a simple string value.
<apex:param value="123" assignTo="{!ListValue[1]}" />
The exception is java.lang.ClassCastException: java.lang.String cannot be cast to common.formula.FormulaFieldReference
I think I understand the basics of the problem - Salesforce can't create a setter reference that includes an index parameter (meaning only setters that take a single parameter can be referenced).
Is there any way around this, or do I just have to create a massive amount of ListValue1, ListValue2 variables and associated code?
It's a hack, but it avoids you having to create dozens of variables.
<apex:param value="1:123" assignTo="{!smartAssigner}" />
Then in your controller:
public void setSmartAssigner(String myval) { // parse the colon, set list value appropriately.
You get the idea.
I've never come across a way to do this in the style you're requesting, I'd suggest that to get this going the easiest thing to do would be to concatenate the values you want into one parameter and then split them back up inside the controller.
You might find a suitable way to do this with <apex:repeat> but I'm not sure on your full use case.

Resources