Vaadin 14 TreeGrid - Cannot add the same item multiple times - vaadin

Working on a project that will display hierarchies of "tasks". I'm running into a problem where it will not allow for multiple entries of the same object. From what I can tell, the "duplicate" item is under a different parent.
The domain data allows for this - a given task may appear in lots of places.
It would seem that this is intentional (maybe), but is there a way around this?

It's intentional to a degree; each Grid and TreeGrid data item is expected to be unique. You could work around this by creating your own implementation of the hierarchical DataProvider class (for example extend AbstractHierarchicalDataProvider) which overrides the getId method along with the other required methods. The return value of this method needs to be unique per item, as it's used as a hash key.

Well, this is probably not the best solution, but it works.
I added a field to the abstract super class that is initialized with the current time (long ms). When I am adding items to the tree grid, I check to see if the tree contains the item and if so, I randomize the field and then add it. The new field is marked #Transient so it's not persisted.

Related

ComboBox with hidden keys

Is it possible in vaadin 12 to have comboboxes such that it displays a user-friendly value but behind the scenes it stores a hidden code? I found this example from 5 years ago but it doesn't apply to Vaadin 12 comboboxes: https://vaadin.com/forum/thread/7821327/combo-box-hidden-values
(If there's a good, reasonably clean way to do it, please point me in the right direction! I would think this is a common sought-after feature)
Items are assigned to ComboBox either directly using setItems or indirectly through setDataProvider.
The item itself is not sent to the browser and shown in the dropdown. Instead, for each item ComboBox generates a string label that is shown in the UI and an internal id that is used on the server for mapping back to the original item instance when the user makes a selection.
The generated id is internal to ComboBox and has no external meaning. In particular, it's not based on any value in the item itself such as the item's primary key in the application's database.
The label is by default based on doing toString() for each item. You can customize how the label is created by assigning an item label generator callback that receives an item instance and returns the label string to use for that item.
If you for example have a combo box for selecting persons, then you could configure it in e.g. this way:
ComboBox<Person> personSelector = new ComboBox<>();
personSelector.setItems(allPersons);
personSelector.setItemLabelGenerator(person ->
person.getFirstName() + " " + person.getLastName());
If I understand you correctly, there is built-in feature in ComboBox for this, the method is called setItemLabelGenerator(..), which allows to define e.g. lambda expression that returns String which is used for ComboBox items instead of the property from underlying data object.
The linked Forum discussion you found is about similar thing in our previous generation of the framework, there has been some renaming of the API here.

Vaadin: How to remove item from DB container grid

How do I remove a row from a container/item/grid/db/entity/bean/class/object/ID?
Also, what's the difference between all these?
Everyone seems to say these as if they were interchangeable.
Can I get a simple explanation of how these all work together?
I've been through dozens of youtube videos and tutorials, but I still can't see the big picture.
Simple task: Delete one row from a grid.
But then it starts getting bigger and more complex with nested beanitem container property field entities and I just can't make sense of it.
Thank you for all of your help in advance!
The Grid, Table or any other Vaadin Component used to present set of data use some implementation of the Container to store your data. A Component is a part of your User Interface, the <div> in your DOM which is seen by your end user. The Vaadin Containers contains your objects. The most widely used containers are:
IndexedContainer - default container for Grid and Table. You usually add items by calling addItem method on either container or related component. The disadvantage of using this type of container is that you are usually obligated to set appropriate properties (think of columns) on both items and the container itself,
BeanContainer - is able to receive Java objects that follows JavaBean convention. Thus it is able to automatically infer properties of your component,
SQLContainer - contains data stored in database. Constructed using SQL query. Can be setup to automatically update your database based on changes made by user in UI.
Items and IDs
Adding single items to some containers may look a bit complicated. There are a few ways to do this. They are described very well on a Vaadin website. Basically the ID is an unique object that you use to access corresponding Item. The Item is represents the single row in your component. Every Item have properties. You can access and make changes to your items in container using their IDs i.e.
table.getItem("uniqueId");
Usually, you don't operate directly on containers. The components expose basic Container interface methods via their API. In example implementation of AbstractSelect.getItem() component currently (Vaadin 7.5.9):
protected Container items;
public Item getItem(Object itemId) {
return items.getItem(itemId);
}
(AbstractSelect is a super class of other Vaadin components like Table and Grid)
It gets more complicated with properties of the items. Every Item have some properties (columns). And every Property has its corresponding ID. Using property ID you can access the value of the item in the specific column. The following code presents above - it adds one item with one property and sets its value:
Table table = new Table();
table.addContainerProperty("column1", String.class, "defaultValue");
Item item = table.addItem("uniqueId");
item.getItemProperty("column1").setValue("Black Friday");
Notice that it is perfectly safe to use String literals as IDs since underneath they are compared using equals()

Can Orbeon controls have multiple values?

I think the answer is no, but the question has been put to me so I'd like to confirm. My understanding is that any custom XBL control that I create for use in Form Builder can have one and only one value. Is this correct?
I have always assumed this because the control name is then used in the data instance as the name of the node which contains the the value.
This question comes from the desire to have reusable components with multiple values, for example, an Address control so that addresses can be recorded consistently and the same set of fields does not need to be added many times. Orbeon does have some support for this in the form of Section Templates but because the control names stay the same in each instance of a Section Template this does not work well with our design.
The best idea I've had is that a custom control which records multiple values could encode all the values into a single text string for example in JSON. Of course, this is not ideal.
Are there any other options?
It is possible for controls to have multiple values. When that happens the values are typically stored in nested elements. I.e. a control could bound to an element <address>, and could create nested elements <street>, <city>,<country>, etc to store the different parts of the address.
In practice, you can look at how this is done in the Image Annotation annotation control (see wpaint.xbl), which creates nested elements <image> and <annotation>, leveraging the xxbl:mirror="true" functionality.

breeze: validating navigation property on change

I have a navigation property, which I added a custom validator to.
The validator triggers fine when saving the entity. However it does not trigger when adding/removing entities from the navigation property.
Should I subscribe to propertyChanged event, or is there another way to handle this ?
Also, why is there not a propertyChanged event per property instead of having to subscribe to any properties change ?
There are two kinds of navigation properties, scalar and nonscalar. A scalar property is something like 'Order.Customer' where an order has a single customer associated with it. Setting or changing the customer in this case will fire the entityAspect.propertyChanged event.
For a nonscalar property like say 'Customer.Orders', accessing the property returns an array of orders associated with the customer.
This is always the same array. Orders can be added or removed from it, but the returned array itself is always the same. Because the array itself is never changed a property change is NOT fired for these operations.
However you CAN watch the array itself for changes, see the arrayChanged event
in the breeze Api docs.
As for why there is no separate event that you can register to fire only when a specific property is changed, the reason is that the current mechanism supports your ability to do this while at the same time allowing for those use cases where you want to see 'all' of the changes to an entity without having to register what could potentially be tens of thousand of events.
Remember entity property level events, if they existed, would have to be registered on as many entities as are in your cache (100's or 1000's) times the number of properties on your entities (5-50).
Most of what is described here is fairly standard for entity change tracking in a number of environments across a variety of programming languages. We didn't try to reinvent the idea, but simply reimplemented a pretty common standard.

Showing many tables in many dropdown lists. c#, asp.net-mvc, linq2sql

I want to use an example to explain what I want.
Assume I've following DB design:
Item (id, name, categoryID);
Category (id, name);
When user wants to create an Item (fill in form), I'll give a list of categories in a dropdownlist, and when user chooses one of the categories ASP.NET MVC will automatically bind categoryID, to the selected one. I need to present same dropdown list when editing the item with correct selected one.
Question:
But my DB is very big, and it requires around 30-40 (maybe even more) category-like tables, that contain just "id" and "name", and all tables need to be shown in dropdown list while creating some other object, and also needs to be presented while editing the object. Definitely above schema doesn't work, because it's tedious to write same logic 100 times with just different table names. (I'm using Linq2SQL)
Currently my solution is:
Make a view that's based in all such tables and in application I just call a function that construction dropdownlist from that single view. But it's still tedious to change view definition everytime I add a new table.
Do you guys think of a better solution for this tedious work, possibly using reflection or some other tecnologies.
It is not a problem "Definitely above schema doesn't work, because it's tedious to write same logic 100 times with just different table names."
If I were you, I will mark an addition interface on these class using "partial class" feature.
Then, I will write few extension method for the partial class.
If anyone interested in the solution:
I've used reflection to solve this problem.
I use reflection over DataContext to get the Table (by string name), and get its fields and construct the optionlist.

Resources