Access to the internal API of the Grid [1-2]
Describe your motivation
In Jmix, we are trying to develop a component based on the Grid. During the process, we faced issues with the private access of some methods and classes of the Grid.
Describe the solution you'd like
We would like to have the ability to override or change the logic of the Grid in the following cases, if possible:
-
Grid.Columnclass.-
A getter method for
componentCallback.// New property to store the callback private SerializableFunction<T, ? extends Component> componentCallback; // The existing setter public Column<T> setEditorComponent( SerializableFunction<T, ? extends Component> componentCallback) { // ... if (editorRenderer != null) { editorRenderer.setComponentFunction(componentCallback); // Here store the component function this.componentCallback = componentCallback; } return this; } public SerializableFunction<T, ? extends Component> getEditorComponentCallback() { return componentCallback; } -
A getter method for
sortOrderProvider:public SortOrderProvider getSortOrderProvider() { return sortOrderProvider; } -
A getter method for
comparator.public SerializableComparator<T> getComparator() { return comparator; }
The main goal of these changes is to be able to copy the whole state of a detached column and then apply it to another column (e.g., one newly added to a
Grid). Could you clarify if there is a simple way to copy the state from one column to another? Or perhaps is there a better way to do this? -
-
Columndata generators.Adding a generator using a separate protected method: in constructor and in
setRenderer()method.-
The case in constructor:
public Column(Grid<T> grid, String columnId, Renderer<T> renderer) { // ... if (dataGenerator.isPresent()) { columnDataGeneratorRegistration = addDataGenerator(dataGenerator.get()); // To be used here } } -
The case in
setRenderer()method:public Column<T> setRenderer(Renderer<T> renderer) { this.renderer = Objects.requireNonNull(renderer, "Renderer must not be null."); // ... columnDataGeneratorRegistration = rendering.getDataGenerator() .map(dataGenerator -> addDataGenerator(dataGenerator)) // To be used here .orElse(null); // ... return this; } -
The protected
addGenerator()method:protected Registration addDataGenerator(DataGenerator<T> dataGenerator) { return grid.addDataGenerator((DataGenerator) dataGenerator); }
In the Jmix component, we should control the generated data from data generators in a
Columndepending on the item. This component uses data generator wrappers when a new generator is added.
Is it possible to add a protectedaddGenerator()method to aColumn? Or is there perhaps a better way to override the current logic? -
-
Grid.DetailsManagerclass.- The protected access to the class:
protected class DetailsManager extends AbstractGridExtension<T> { // ... } - A protected separate method for creating an instance:
protected DetailsManager createDetailsManager() { return new DetailsManager(this); } - The method in a constructor:
protected <U extends GridArrayUpdater, B extends DataCommunicatorBuilder<T, U>> Grid( int pageSize, SerializableBiFunction<UpdateQueueData, Integer, UpdateQueue> updateQueueBuilder, B dataCommunicatorBuilder) { //... detailsManager = createDetailsManager(); // To be used here // ... }
For the same reason as in the previous case (controlling generated data from data generators in a
Column), we need to override theDetailsManagerin theGrid.
Is it possible to add a protected method to theGridto override theDetailsManager? Or is there perhaps a better way to override the current logic? - The protected access to the class:
-
Grid#generatePartData()andGrid#generateSelectableData()methods- The protected access to the
generatePartData()method:protected void generatePartData(T item, JsonObject jsonObject) { // ... } - The protected access to the
generateSelectableData():protected void generateSelectableData(T item, JsonObject jsonObject) { // ... }
In the Jmix component, we need to slightly change the logic of the
generatePartData()andgenerateSelectableData()methods, but their access is private. Is there a simpler way to override these methods? - The protected access to the
Describe alternatives you've considered
No response
Additional context
No response
Could you clarify a few points regarding your suggested solutions?
- Is the case equivalent to adding back a column that has been previously removed via
removeColumn? Or would hiding the column instead of removing help? - Regarding introducing API for adding data generators to columns, could you give some examples on what kind of adjustments do you need on the columns?
- Again, for modifying the part data and selectable data, can you provide an example on what you are trying to achieve? For example would the combination of
setItemSelectableProviderandaddDataGeneratornot provide the required modification?
Hello @ugur-vaadin,
- Yes, this is a case where a removed column is adding back. We abandoned the idea of hiding the column using the visible property because, in our case, users control the visibility through a separate component.
To better understand why some API elements do not suit the Jmix component: the component contains items that, in some cases, should not be accessible through the public API or should be accessible but as a different type. For example, when such an item is clicked, we should not invoke details for that item.
-
It would be helpful if the Column class had a protected method for adding a data generator to a Grid. I provided an example in the issue description at point 2). I would use
Grid#addDataGenerator(), but I cannot detect which data generator belongs to a column. The reason for this change is that we need to control the generated data in a column for specific rows. -
The
setItemSelectableProvider()is a good option. I've checked, and we can use it, thank you for the suggestion. The case for the part data generator is as follows. In the Jmix component, we split the part name generator function into:- Group part name generator, which takes a different type (not the item type);
- Part name data generator, which is the same as
setPartNameGenerator().
Depending on the item, the required generator is invoked. This feature exists for both the
ColumnandGridclasses. Therefore, in thegeneratePartData()method, we should invoke not justpartNameGeneratorbut a general function or method that decides which generator to invoke. For example:@Override protected void generatePartData(E item, JsonObject jsonObject) { // ... String rowPartName = partNameGenerator.apply(item); // invoke e.g. generatePartName(item); // ... getColumns().forEach(c -> { DataGridColumn<E> dataGridColumn = (DataGridColumn<E>) c; String cellPartName = dataGridColumn.getPartNameGenerator().apply(item); // invoke e.g. dataGridColumn.generatePartName(item); // ... }); // ... }