vaadin flow grid get row in edit state - grid

I am using a grid in vaadin flow. When it is a row in edit state I would like to get the row index of the grid.
I guess I have to use the following but I can't make it.
grid.getEditor().isOpen();
grid.getEditor().getItem()
Can you help me?

You could look up the item in your grid's collection:
grid.getEditor().addOpenListener(event -> {
System.out.println("Opened editor on item " + myItems.indexOf(event.getItem()));
});
Although the 'index' will be the index in that collection rather than the index in the displayed grid, which is influenced by the sort order and filtering. I believe that not exposing an index on the EditorOpenEvent is intentional, as the concept of an index is presentation specific and abstracted away from the server-side initialization of the grid.
If you really needed to get to the index of the row in the current grid presentation (which respects sort order), you could make a Javascript call. Given this isn't part of the documented API, it's likely subject to change.
PendingJavaScriptResult pendingJavaScriptResult = grid.getElement().executeJs("return this._focusedItemIndex");
pendingJavaScriptResult.then(jsonValue -> {
System.out.println("From JS:" + jsonValue.asNumber());
});

Related

QML TableView access model properties from delegate

I have a TableView for which I've defined my own itemDelegate. Now, from within this delegate I can access the value for the column using styleData.value, but I'd also need to access the other properties in this same item but I can't find how to.
I need this, because the text styling needs to change depending on some other property of the item model.
Any ideas? thanks!
There is some documentation missing. Within the item delegate you can access the following (taken from the source code of TreeView.qml):
styleData (see documentation)
model (currently not documented)
modelData (currently not documented, not sure about this but I guess it's similar to ListView)
(By the way, what's also missing in the documentation but which is useful is styleData.role. Also, the documentation of the other delegates lacks some available properties too; the best is to peek into the source code of the QML file and have a look for the Loader element which instantiates your delegate. As a plus you learn how that creepy stuff works. ;))
With model and the row/column information you can then navigate to the item data. This code depends on the type of model.
If you're using QML's ListModel, then you can use model.get: model.get(styleData.row)[styleData.role] should then work (untested since I use it rarely, please give feedback).
If you're using a C++ QAbstractItemModel or friends, the best is to add a slot to the model class which takes just the row and role name, since that's the information the TableView works with (nor with role numbers nor with columns...).
However in both cases you shouldn't use the expression in a property binding! The notification system will not work since you don't use the property system for accessing the data. According to your question, I guess you wanted to use it in a expression with binding. I don't know how to properly listen to changes in the model manually.
An alternative approach is to access the other items of the row and provide a property there. Some hints:
From within one item, you can access other items of the same row by walking the object tree up twice (first to the Loader which instantiates your component, then to the actual row) and then down twice (first to the particular child object which is a Loader, then its instantiated item). You need to know the column number you want to access (not the role name), I assume you want to access the first column (index 0):
parent.parent.children[0].item
You can provide the model data using a property in each item. Assuming a simple Text element this might be:
Text {
property variant value: styleData.value // <-- Here you make it available
// your other stuff
}
Putting them together could look like the following. In this example I assume the first row contains an integer, and if it is zero, the second column should be red.
// (within TableView)
itemDelegate: Text {
property variant value: styleData.value
text: styleData.value
color: (styleData.column == 1 && parent.parent.children[0].item.value === 0)
"red" : "black"
}
I think it's pretty easy if you read the source code of TableViewItemDelegateLoader.qml (it is a private code in qtquickcontrol)
To access any role you use use : model[your_role_name] .
For exp: model["comment"]
Faced with same problem today, this is result of my investigations (Qt 5.2.x)
If you have hard limit to TableView, there is only one correct solution - use model.get(styleData.row)["roleForStyling"] as #leemes wrote. But it will very slow if you have big amount of data in model and using, for example, proxy model for sorting/filtering.
Direct solution from #leemes answer is great, but in general case not be working, because in TableView any Item wrapped in Loader and therefore independent from parent and other items:
When some item is created (where you want to change text style)
another element (from which to receive identity) cannot yet be
created
You may not have "parent" on item creation (i.e. binding will
be broken)
In my case, the best solution for deep customise was creation of the simple wrapper for ListView. In this case you have access for complete row data in delegate without the overhead. Highlights for making component ("My own ListView as table"):
Create standalone header (Rectangle or Item) - do not use header form ListView.This make it fixed for any amount of data.
Wrap ListView to ScrollView (if you need scrollbars)
Use Clip: true property in list for make correct
Set style for highlight and set highlightFollowsCurrentItem:true in ListView
As bonus in future this may be used for make "TreeTable" :)

Databinding with a large amount of values and getter methods?

Reading through Misko's excellent answer on databinding here: How does data binding work in AngularJS?, I am wondering how Angular does it's dirt-checking behind the scenes, because:
I'm creating an app, that prints a large amount of Car objects to the DOM, each Car looking something like this:
var Car = function(settings) {
this.name = settings.name;
+ many more properties...
}
Car.prototype = {
calcPrice: function() { ... },
+ many more methods...
}
$scope.cars = [lots of Cars];
The linked answer above mentions a limit of around 2000 values that can be provided through databinding when printed in the DOM, and due to the large amount of properties on each Car object, this number could very easily be exceeded in this app when looping through the cars array.
Say you end up having 2000+ values printed in the DOM through databinding, and one of these values updates, does it affect Angular's dirt-checking performance that 2000 values are present, or does Angular somehow flag the values that change, so it only looks at the changed values when running its $digest()? In other words, does it matter that you have a lot of databound values, when only a very small number of these are likely to be updated after the initial print?
If it does matter, -- and since most of the values are read-only -- is there some way to use the databinding syntax {{car.prop}} to get the value to the DOM once and then tell Angular to not bind to them anymore
Would it make a difference to add getter-methods to the Car object and provide it's properties like this {{car.getProp()}} ?
I had the same kind of problem with an application I was working on. Having a huge data set is not a problem, the problem comes from the bindings,ng-repeats in particular killed performances.
Part of the solution was removing "dynamic" bindings with "static" bindings using this nice library: http://ngmodules.org/modules/abourget-angular.

How to traverse/rebuild UIComponent tree structure in Flex

I have some kind of UIComponent grouping which may look something like this with the classes "Group" and "Element".
Groups can have children and children may be elements or groups again, basically similar to a file system or the str+g group function in several graphics programs. The simplest form of a group is a group with only children which are also the most low level groups in the tree.
Edit:
The display hierarchy is already existant, i try to persist it to xml.
Group
- element
- Group
- element
- Group
-element
-element
- element
- element
I want to rebuild this structure in an xml-document for persistence.
I know how to build an xml document in Flex but not how to (recursively) traverse this n-tree correctly.
Update:
For getting only the child nodes one could make use of the following algorithm (pseudo code). But somehow i don't understand how to create the xml from this.
walkTree(group) {
children = node.getChildren
if(children != null) {
for(int i=0; i<children.length; i++) {
if(children[i].isGroup()) {
walkTree(group[i]);
} else {
trace(child);
}
}
}
}
As a starter, I'd suggest this : http://www.sephiroth.it/tutorials/flashPHP/E4X/
So, basically, what you are looking for seems like E4X in Actionscript 3
My suggestion would be to have your structure be data driven from the start, so the XML controls the draw of the screen. Then you would have the XML and wouldn't need to make it.
However, if you really want to do this, you'll need to loop through all the children at each level and add some sort of node that describes the child. However, if you don't have a view that is data driven, I don't see what good this will do you (and if you do, and it's not XML, you're better off writing data export from the data side, not the view side).

'Pre-measuring' Flex Components

I'm implementing a custom Flex component that provides a scrollable viewpoint onto a (possibly very large) data grid. I'm using the ItemRenderer pattern, such that I only have UIComponents for the elements visible on the screen at a given time. In other words, something similar to the standard DataGrid control.
One requirement I have is to dynamically size the grid cells to fit the provided data, such that the column widths and row heights are known up front. (The column widths and row heights can't fluctuate as the user scrolls and new cells come into view.)
This requirement implies a 'pre-measure' phase of the entire grid to be performed when the component's dataSource or itemRenderer is changed. I'd like to use the standard Flex component measuring operations to perform this pre-measurement phase.
My current strategy for this pre-measure phase is to:
Obtain an itemRenderer instance
Initialize the itemRenderer
For each cell in the data source:
Set the itemRenderer's 'data' object to that cell's data
'commitProperties()' on the component
'measure()' the component
Update column width/row height appropriately based on measurement results
I'd rather not attach the itemRenderer to the application's display list, but that means it won't be initialized by the framework. Also, I need the renderer's initialization and commitProperties/measurement phases to occur synchronously. I'm scared of how much of the Flex component lifecycle management framework I'll have to replicate to accomplish this.
So I call on those more experienced than I for words of wisdom:
Any thoughts on the feasibility of this strategy?
Any suggestions on how I could elegantly make use of the framework to perform this measurement for me?
Any better strategies to determine cell size?
I studied the framework code a bit, and if initial results are an indication, this isn't as painful as I feared. The guts of it:
var renderer:IListItemRenderer = getRenderer();
renderer.initialize();
for each (var cell:Object in cells) {
renderer.data = cell;
renderer.validateProperties();
renderer.validateSize(true);
// Access renderer's size properties here
}
Passing the 'recursive = true' flag to validateSize is the key that I was missing previously. Unfortunately there's no equivalent flag for validateProperties, so I'll probably have to implement that myself to make it reliable for arbitrary ItemRenderers.
I've never applied itemRenderers this way, so, not sure how much this would come into play with you're approach, but are you setting
super.data = data
at the top of your renderer's data setter? i.e:
override public function set data(value:Object):void
{
super.data = value;
...
}
If not, you might try adding that and see if it removes the need for a recursive flag in validateProperties().

Removing rows from QTreeWidget (qt programming)

what's the best way to remove a row (QTreeWidgetItem) from a QTreeWidget?
The QTreeWidget content has been set by:
myQTreeWidget->insertTopLevelItems(0, items); // items = QList<QTreeWidgetItem*>
then I remove an item from my QList "items" and I try to clear/reset the QTreeWidget
packList->clear();
packList->insertTopLevelItems(0, items);
but my app crashes here!
Suggestions?
Your problem is that calling packList->clear() deletes the tree widget items contained by the tree. (See the documentation about QTreeWidget::clear(), which includes a note about the items being removed from the tree before deleting.) You'll either need to find a way to remove the items, or not maintain a list of them separately from the tree.
On a slightly-related note, if you are trying to keep track of other data along with the tree, I'd recommend you try to use the models paradigm. In non-trivial cases, it has usually been worth my while to convert to that technique, rather than using the widgets/items.
From what this documentation says, you should be able to do it with:
packList->takeTopLevelItem(index);
Which returns removes and returns the item at the supplied index.

Resources