I develop web part with custom editor part and faced with this question.
Is it possible in web part set Personalizable attribute to generic List?
For example I want something like this:
[WebBrowsable(false)]
[Personalizable(PersonalizationScope.Shared)]
public List<AnnouncementItem> Announcements
{
get { return _announcements; }
set { _announcements = value; }
}
Is it possible, and what kind of types at all can be used as "Personalizable"?
Thanks.
Solution:
I use a custom EditorPart to select multiple lists using AssetUrlSelector, but I need a way to personalize this collection for end user.List<of custom objects> doesn't work, but I found that List<string> (and only string) work perfectly. So, I get required lists in EditorPart and pass their to the web part using List<string>.
Try using a custom EditorPart to add/remove items from the collection. I've never built a web part that personalized a collection so I don't know if it works but I'd definitely try the collection with an EditorPart. If it doesn't work, serialize XML into a string property.
Your question does not seem to match your code. Your code shows a collection of custom objects. I doubt an end user will be able to set such a property. To have a property that points to a generic list, you would probably be better off defining the property as a string that contains the URL to a list.
Related
I've been stuggling for a moment and I'm unable to find anything related to that. I'm a total newbie with Kendo, and sadly I was not able to find anything that could help my question, documentation, forums and all of that : they haven't helped at all.
Situation :
I have a viewmodel in my ASP .NET app. I'm trying to make a chart out of one of the proripeties called "Type". This propriety represent a type of data - let's say fruits, like "Banana", "Apple" etc.
This type contains only and only one type at the time. It cannot contain something like "Apple and bananas". It's always a string, too.
This proriety is part of a larger model. But I'm only interested in this one.
Now, what I like to do :
I'd like to make a chart, using Kendo, from that propriety.
That means, I have to bind my chart to my model, and then, it will be able to know how many time some of those Types were used.
Like, example, If I have three objects :
Name : "Mjuzl"
Type : "Potato"
Name : "Uijqf"
Type : "Apple"
Name : "Zjli"
Type : Potato"
I'd like my char to count that my model used the type Potato twice, and the type Apple once.
I know how to get my datasource that contain all of the objects that use my model. (I have already used Kendo Grid just before but it's so simplier tbh) My issue right now, is that I have no idea - and I wasnt' able to find any - how to actually display what I want in my chart. I say it again, they are strings. I know how to get my datasource. I don't know how to actually show what I want to show. (Should I use columns ? sections ? I don't know)
Do I need to build a JSON from my controller that will ask the database to count ? Does Kendo is able to do it by it's own ? I'm so lost, I have no idea what Kendo is actually waiting for to make my chart working. The documentation isn't helping at all. I've been researching for a while, I haven't found anything that describes the exact same problem. And I've been searching for days.
Very badly drawn image I've done to put a picture on my problem :
I don't ask to do it for me, I ask for a path. A way to do it.
Thanks.
One way would be to create a view model specifically for your chart, and you can populate that view model based on your data.
Roughly (untested code - just to give you an idea), something like this:
public class MyChartViewModel
{
public int TypeCount { get; set; }
public string TypeName { get; set; }
}
and then in your read method for the chart where you are populating MyChartViewModel:
var myExistingDataModel = howeverYouGetYourDataHere;
var model = new MyChartViewModel();
var distinctTypes = myExistingDataModel.Select(x => x.Type).Distinct().ToList();
foreach (var distinctType in distinctTypes)
{
model.TypeCount = myExistingDataModel.Count(x => x.Type == distinctType);
model.TypeName = distinctType;
}
Finally ! I managed to do it !
For any future reference :
Based on G_P's answer, I used a LINQ request to count all of my types : Linq distinct - Count (don't forget to remove the .District() otherwise I won't work !)
Then, I did some debuging to see if I actually return my data, because nothing was showing in the chart. It did return my data and the right number.
The issue for this case was, I use
return Json(types.ToDataSourceResult(request, ModelState));
To return my data to my chart. But ! there is a little thing to know about Chart, they don't work like grids. You have to use a specific setup for showing your data if you use ToDataSourceResult : https://docs.telerik.com/aspnet-mvc/html-helpers/charts/data-binding (See "3) (Optional) Configure a Custom DataSource."), just change the call to your controller, and voilĂ ! It worked !
We have a Set<String> that we are printing to the page in Thymeleaf:
<h5>Unique Students names</h5>
<ol>
<div th:each="uniqueName: ${course.uniqueStudentsNames}">
<li th:text="${uniqueName}"></li>
</div>
</ol>
Since it is a Set<String> there is no order of the items in the set.
We like to convert the non-ordered Set<String> to an ordred List<String> so we will be able to print it by ABC. Since it is a UI issue, we don't like the backend to change its data structure.
An option we thought about is to create such a list in the Model:
model.addAttribute("course", course);
model.addAttribute("orderedList", /* convert Set to ordred List */);
But this seems very strange that the Model needs to handle such a UI issue.
Is there a way to do it in Thymeleaf?
Instantiate it as a TreeSet (you are probably using hashset?) and you have a set with the ordering behaviour you want. Set<String> (Set<anything> really) guarantees there won't be repeated items, but it does not imply anything about the order/unorder.
On the other side, thymeleaf, as a template engine, won't do such things as adding ordering behaviour to a collection that does not implement it. The most it will do is allow you to access methods of the collection; in the case of set: set utility methods.
If you no matter what want to use a non ordered set, you'd have to use something like javascript to manipulate the items on the client to order them.
Use the Thymeleaf utility method to convert the object to a List:
${#lists.toList(object)}.
Then perform a utility operation to sort as needed from there, optionally using your own Comparator.
The current Thymeleaf source code shows that the toList() method will check if the target object is an instance of Iterable. In your case, Set implements the interface.
To reference the external link:
if (target instanceof Iterable<?>) {
final List<Object> elements = new ArrayList<Object>(10);
for (final Object element : (Iterable<?>)target) {
elements.add(element);
}
return elements;
}
I'm planning on allowing a client to provide a couple codes for each product that I'll need to reference with Javascript on the product pages.
Basically my plan was to use the Big Commerce's 'custom fields' to do so, but I'm having trouble spitting out the custom fields onto the product pages. I've been looking all over for some type of GLOBAL variable that allows me to reference custom fields, but I'm coming up dry. I would think there would be some type of GLOBAL array with all the custom fields in it, or a way to reference them by name directly.
Am I blind, or is there just no way to do this directly in the BC template file?
Thanks.
In Bigcommerce the custom fields can generally be found within the ProductOtherDetails.html Panel which contains a Snippet named ProductCustomFieldItem.html. This snippet has the markup for each custom field that the system outputs.
Inside of the ProductCustomFieldItem.html Snippet are the two codes you are looking for: %%GLOBAL_CustomFieldName%% and %%GLOBAL_CustomFieldValue%%.
I ran into this as well - given that it's quite a long time later, I'm supposing there's no better answer - a decent amount of searching turned up nothing useful as it seems all you can do is output the full set of custom fields as a set of divs.
So, I output them into a div which was hidden:
<div id="fpd-custom-fields" style="display:none;">
%%SNIPPET_ProductCustomFields%%
</div>
and then set up a javascript function to get the value based on the name:
function getCustomFieldValue(label)
{
var value = '';
$('#fpd-custom-fields div.Label').each(function()
{
if($(this).text().toLowerCase() == (label.toLowerCase() + ':'))
{
value = $('div.Value', $(this).parent()).text().trim();
}
});
return value;
}
Doesn't feel quite right as it's not a very clean solution, but was the best I could come up with unfortunately!
I have this code in my controller:
def cols = grailsApplication.getDomainClass('com.archie.Build').persistentProperties.collect {it.name}
The code above will allow me to list all the property names I have in Build class. Now, I would like to include also the properties data type, ie. boolean, String etc...
Somewhat like the output is:
[floorType:String, floorWidth:Float, ......]
Maybe not exactly like that, or maybe similar, but as long as I can return their data type. Can someone help? Thank you.
Each entry in persistentProperties is a GrailsDomainClassProperty, and this provides access to the type of the property as a Class object:
def props = [:]
grailsApplication.getDomainClass('com.archie.Build'
).persistentProperties.each {
props[it.name] = it.type.name
}
Or just pass the persistentProperties array itself through to the GSP, then extract .name and .type there.
You may also wish to consider using constrainedProperties instead of/in addition to the persistentProperties. The constrainedProperties map lists only those properties that are mentioned in the domain class constraints block, but the iterator over this map is guaranteed to return the properties in the order they are listed in the constraints. This is how the default scaffolding operates, as I'm not aware of any way to control the order of the persistentProperties array.
I'm working on an application at the moment in ASP.NET MVC which has a number of look-up tables, all of the form
LookUp {
Id
Text
}
As you can see, this just maps the Id to a textual value. These are used for things such as Colours. I now have a number of these, currently 6 and probably soon to be more.
I'm trying to put together an API that can be used via AJAX to allow the user to add/list/remove values from these lookup tables, so for example I could have something like:
http://example.com/Attributes/Colours/[List/Add/Delete]
My current problem is that clearly, regardless of which lookup table I'm using, everything else happens exactly the same. So really there should be no repetition of code whatsoever.
I currently have a custom route which points to an 'AttributeController', which figures out the attribute/look-up table in question based upon the URL (ie http://example.com/Attributes/Colours/List would want the 'Colours' table). I pass the attribute (Colours - a string) and the operation (List/Add/Delete), as well as any other parameters required (say "Red" if I want to add red to the list) back to my repository where the actual work is performed.
Things start getting messy here, as at the moment I've resorted to doing a switch/case on the attribute string, which can then grab the Linq-to-Sql entity corresponding to the particular lookup table. I find this pretty dirty though as I find myself having to write the same operations on each of the look-up entities, ugh!
What I'd really like to do is have some sort of mapping, which I could simply pass in the attribute name and get out some form of generic lookup object, which I could perform the desired operations on without having to care about type.
Is there some way to do this to my Linq-To-Sql entities? I've tried making them implement a basic interface (IAttribute), which simply specifies the Id/Text properties, however doing things like this fails:
System.Data.Linq.Table<IAttribute> table = GetAttribute("Colours");
As I cannot convert System.Data.Linq.Table<Colour> to System.Data.Linq.Table<IAttribute>.
Is there a way to make these look-up tables 'generic'?
Apologies that this is a bit of a brain-dump. There's surely imformation missing here, so just let me know if you'd like any further details. Cheers!
You have 2 options.
Use Expression Trees to dynamically create your lambda expression
Use Dynamic LINQ as detailed on Scott Gu's blog
I've looked at both options and have successfully implemented Expression Trees as my preferred approach.
Here's an example function that i created: (NOT TESTED)
private static bool ValueExists<T>(String Value) where T : class
{
ParameterExpression pe = Expression.Parameter(typeof(T), "p");
Expression value = Expression.Equal(Expression.Property(pe, "ColumnName"), Expression.Constant(Value));
Expression<Func<T, bool>> predicate = Expression.Lambda<Func<T, bool>>(value, pe);
return MyDataContext.GetTable<T>().Where(predicate).Count() > 0;
}
Instead of using a switch statement, you can use a lookup dictionary. This is psuedocode-ish, but this is one way to get your table in question. You'll have to manually maintain the dictionary, but it should be much easier than a switch.
It looks like the DataContext.GetTable() method could be the answer to your problem. You can get a table if you know the type of the linq entity that you want to operate upon.
Dictionary<string, Type> lookupDict = new Dictionary<string, Type>
{
"Colour", typeof(MatchingLinqEntity)
...
}
Type entityType = lookupDict[AttributeFromRouteValue];
YourDataContext db = new YourDataContext();
var entityTable = db.GetTable(entityType);
var entity = entityTable.Single(x => x.Id == IdFromRouteValue);
// or whatever operations you need
db.SubmitChanges()
The Suteki Shop project has some very slick work in it. You could look into their implementation of IRepository<T> and IRepositoryResolver for a generic repository pattern. This really works well with an IoC container, but you could create them manually with reflection if the performance is acceptable. I'd use this route if you have or can add an IoC container to the project. You need to make sure your IoC container supports open generics if you go this route, but I'm pretty sure all the major players do.