Здравствуйте!
Studio и Jmix 2.4.3.
Есть некая базовая сущность, допустим Entity
, у сущности помимо прочего есть поле Status
Есть несколько экранов, предположим 8, для отображения списка сущностей по статусам. Каждый из этих экранов имеет genericFilter
и dataGird
. Было несколько неудобно, так как приходилось копировать один и тот же код фильтра и грида во все 8 экранов.
С выходом fragments
мелькнула возможность решить этот вопрос, создав фрагмент с компонентом GenericFilter
и фрагмент с компонентом DataGrid
, указав для атрибута <collection> provided = true
. И действительно оно сработало, xml
экрана списка значительно похудел, когда его заменили этими двумя фрагментами, а для изменения/добавления пропертей фильтра или колонок грида достаточно поменять их во фрагменте.
Но тут дело дошло ещё до одного экрана, где есть элемент TabSheet
, который содержит две вкладки Tab
. У каждой вкладки Tab
есть те же GenericFilter
и DataGrid
что и в остальных экранах. То есть, в xml экрана определены 2 коллекции со своим названием, например EntityDc1
и EntityDc2
, со своими лоудерами EntityDl1
и EntityDl2
. Соответственно надо каким-то образом указать фрагментам, что для вкладки Tab1
тебе нужен EntityDc1
и EntityDl1
, а для вкладки Tab2
- EntityDc2
и EntityDl2
.
Для фрагмента с dataGrid
это удалось реализовать, устанавливая свой контейнер в каждый фрагмент по его id
.
Спойлер
@Subscribe
public void onInit(final InitEvent event) {
gridFragment1.setDataContainer(EntityDc1);
gridFragment2.setDataContainer(EntityDc2);
}
@FragmentDescriptor("common-grid-fragment.xml")
public class CommonGridFragment extends Fragment<DataGrid<Entity>> {
@ViewComponent
private DataGrid<Entity> entitiesDataGrid;
public void setDataContainer(CollectionContainer<Entity> container) {
entitiesDataGrid.setItems(container.getItems());
}
}
Однако с фрагментом фильтра это никак сделать не удалось. С виду всё было просто, компонент genericFilter
имеет метод setDataLoader(DataLoader dataLoader)
, то есть достаточно передать свои CollectionLoader<Entity>
во фрагменты, но этот метод имеет следующую реализацию:
Спойлер
public void setDataLoader(DataLoader dataLoader) {
checkState(this.dataLoader == null, "DataLoader has already been initialized");
checkNotNull(dataLoader);
this.dataLoader = dataLoader;
this.initialDataLoaderCondition = dataLoader.getCondition();
LogicalFilterComponent<?> rootLogicalFilterComponent = emptyConfiguration.getRootLogicalFilterComponent();
rootLogicalFilterComponent.setDataLoader(dataLoader);
rootLogicalFilterComponent.setAutoApply(autoApply);
}
То есть при попытки установить переданный из экрана loader
в genericFilter
вылетала ошибка метода. Убрать из фрагмента контейнер нельзя, так как у компонента genericFilter
атрибут dataLoader
обязателен, как отменить инициализацию тоже неизвестно, из экрана loader
пытался устанавливать в методе onInit
.
Никакие попытки связать загрузчики/коллекции из экрана и из фрагмента не увенчались успехом, фильтр не работал, вылетали различные ошибки.
Подскажите, есть ли какое решение?
Ссылка на проект-заготовку: