I have this line i an Umbraco solution, which gets me the ids of the nodes selected, comma seperated.
But what i want to get, in a oneliner, is a value of the node(s) selected.
So currently it is just returning the node id like "1001, 1000, 1003" or just "1003" if only one is selected.
What i want it to return, is a value of the selected node. Lets say its a menu title on the property i want. So instead of the above output, i want "Frontpage, Contact, About Us" etc.
How would that look?
var mynode = Page.Cache.GetById(id);
mynode.GetPropertyString("pages")
The simplest way would be to install the Umbraco Core Property Value Converters nuget package. This would then provide you with an extension method that you can use to retrieve a list of nodes in one go. Then you could use LINQ to select the menuTitle property of each page.
var menuTitles = mynode.GetPropertyValue<IEnumerable<IPublishedContent>>("pages")
.Select(x => x.GetPropertyValue<string>("menuTitle"));
If you need to you can then use string.Join() to combine the menu titles to get a comma-separated list.
Here's a list of using statements that you might need to add:
using System.Collections.Generic;
using System.Linq;
using Our.Umbraco.PropertyConverters;
using Umbraco.Web;
using Umbraco.Core.Models;
Related
I have a tagging system in my application. Now there is one specific entity, for which I want to allow only one tag. Actually I want to assign a parent to a tag.
For this purpose I want to use a VaadinCombobox with lazy loading and filtering.
My data layer is Spring Boot Neo4J Data. There I have a repository like this:
Page<TagListDto> searchPaginated(String searchTerm, Pageable page);
This gives me a data transfer object used for list displays filtered by the searchTerm. The list is pageable. I use the same method for filtering Grids.
So I could do it like this, if I knew where to get the searchTerm from.
ComboBoxLazyDataView<TagListDto> dataView = parentTag.setItems(query ->
tagRepository.searchPaginated(searchTerm,
PageRequest.of(query.getPage(), query.getLimit())).stream());
parentTag.setItemLabelGenerator(TagListDto::getName);
But probably, I'll have to use a DataProvider and a FilterBuilder for the ComboBox, right?
So the answer is to use setItemsWithFilterConverter-method. What you enter into the combo-box field will be sent to the filter converter (2nd method parameter) as a String and then passed as property of the query object to execute the search (1st method parameter).
So if you need to convert the type of the search term from String to some other type, add wildcards or whatever, do it in the 2nd labda.
With query.getFilter() in the 1st lambda you can retrieve the search term and then use that to make the query to your backend.
Here's an example:
ComboBox<Person> personComboBox = new ComboBox<>();
personComboBox.setItemLabelGenerator(Person::getName);
personComboBox.setItemsWithFilterConverter(
query -> personService.searchPaginated(query.getFilter().orElse(""),
PageRequest.of(query.getPage(),
query.getLimit())).stream(),
personSearchTerm -> personSearchTerm
);
I am using OData API to read data in my Fiori Application. The issue is, in Odata API, the latest data entry is at the end rather it should be at the top. How do i do that ie put my latest data on top.
You can use the $orderby to decide what order the data is returned in. See the docs for more info. This URL is an example of ordering (using the OData TripPin example service) that sorts by the LastName property:
http://services.odata.org/V4/TripPinServiceRW/People?$orderby=LastName
We can use this same process to order by a DateTime value or an ID value to get your latest entries at the top. For example, here we order by the DateTimeOffset field StartsAt putting the latest entries first:
http://services.odata.org/V4/TripPinServiceRW/People('russellwhyte')/Trips?$orderby=StartsAt desc
1)
As mentioned before, you might have a look at server side sorting using “$orderby” as seen here.
2)
You might also want to check out the following tutorial on Sorting:
“
items="{
path : 'invoice>/Invoices',
sorter : {
path : 'ProductName'
}
}"
We add a declarative sorter to our binding syntax.
As usual, we transform the simple binding syntax to the object notation, specify the path to the data,
and now add an additional sorter property.
We specify the data path by which the invoice items should be sorted, the rest is done automatically.
By default, the sorting is ascending, but you could also add a property descending with the value true inside the sorter property to change the sorting order.”
Please see here and here
3)
This here might also be helpful:
“In this step, we will create a button at the top of the table which will change the sorting of the table.
When the current sorting state of the table is changed, the sorting state will be reflected in the URL.
This illustrates how to make the table sorting bookmarkable.”
Step 13: Make Table Sorting Bookmarkable
Sample: Navigation - Step 13 - Make Table Sorting Bookmarkable
4)
These links here also look interesting:
Sorting, Grouping and Filtering for Aggregation Binding
Sample: Sorting
Sample: With Sorting and Filtering Feature
In a Umbraco 7 solution, i have a Tags Content picker on all pages. Pages can with this, set tags on each page.
I then want to get alle pages, within the intire site, that has, lets say tag 111 (id, not name).
I have tried with:
var ids = Model.MacroParameters["tags"]; //the tags to show
CurrentPage.AncestorOrSelf(1).Descendants().Where(x => ids.Contains(x.tags.ToString()));
But that gives me the error:
Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type
Whats the correct way?
Solved it with;
Umbraco.Content(rootId).Descendants().Where("tags.Contains(#0)", ids);
You have a few options, depending on whether you prefer a dynamic or strongly typed view model.
Strongly Typed API
Umbraco.TypedContentAtRoot().Descendants().Where(x => x.tags.Contains(ids));
Dynamic API
Umbraco.ContentAtRoot().Descendants().Where("tags.Contains(#0)", ids);
Please note that the Contains statement may give you inconsistent results, as the tags property seems to be returning a comma separated list. In that case you can try splitting the string or install the Core Property Value Converters package and get the tags as IEnumerable<IPublishedContent>
Always try to avoid using Descendants, especially on the root node.
To get the tags for a property:
ApplicationContext.Current.Services.TagService.GetTagsForProperty(Model.Content.Id, "propertyname")
To find content with a specific tag:
ApplicationContext.Current.Services.TagService.GetTaggedContentByTag("tag")
I'm trying to create a dynamic survey application in Prime Faces. I have a list of Question Objects that each contains a list of AnswerChoices. These are given to the f:selectItems value attribute. This is fine. The question object also contains a List of selectedValues which is given to the relevant selectOne/many component.
Because I'm looking to be generic, there will be questions that have multiple selected values and also some that have only one selected value. I wanted to be able to point the selectOne and selectMany components to the List of strings within the relevant Question object that represents the selectedValues.
This works ok for the selectMany component, but not for the selectOne component which needs to be pointed at a singular object rather than a list. Is there an easy way around this that I'm missing - as I'd like to only have one object representing the selectedValues if possible
You can use brace notation to bind the value to a list/array item at a specific index. The below example binds the value to the 1st item of the list/array.
<h:selectOneMenu value="#{bean.selectedAnswers[0]}" />
There's however a caveat: you need to prepare the list/array with the single item yourself during bean's (post)construction. JSF/EL won't do that in case of a <h:selectOneMenu>.
E.g.
#PostConstruct
public void init() {
selectedAnswers = new ArrayList<Answer>();
selectedAnswers.add(null);
}
It doesn't harm to reuse this preinitializated property for UISelectMany components by the way.
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.