#wicket
#калитка
Вопрос:
У меня есть столбец в моей таблице, где я заполняю элемент следующим кодом:
@Override
public void populateItem(Item<ICellPopulator<T>> item, String componentId, IModel<T> model) {
if (deleteEnabled(model)) {
item.add(new ConfirmationLink<>(componentId).onClick(target -> deleteRow(...)));
} else {
item.add(new Label(componentId));
}
}
Поэтому, когда у пользователя достаточно разрешений для удаления объекта, он может видеть значок в строке, если нет, он видит только пустую ячейку.
Где я могу проверить для каждой модели в таблице, что у пользователя нет разрешения на удаление любого объекта и предотвращение отображения столбца в таблице?
Обновить
Я хотел бы добавить некоторый код, чтобы объяснить мой случай.
Это очень распространенный пример использования таблицы в моем приложении.
public class CenterPanel extends SWPanel<CourierSearchQuery> {
public CenterPanel(String id) {
super(id, new Model<>(new CourierSearchQuery()));
}
@Override
protected void onInitialize() {
super.onInitialize();
List<IColumn<Courier, String>> columns = List.of(
new StyledColumn<Courier>("Ф.И.О.", "name.FIO", "name.FIO")
.setCreateComponentFunction((id, model) ->
new LinkPanel(id, model.map(n -> n.getName().getFIO()), model)),
new StyledColumn<Courier>("Статус", "state.title")
.setCssClass(CSS.width(100)),
new StyledColumn<Courier>("Телефон", "phone")
.setCssClass(CSS.width(100)),
new DeleteColumn<>() // <- this column should be hideable
);
add(new EntityDataTable<>("table", columns, getModel()));
}
}
Существует объект JPA (Courier), объект параметров POJO (CourierSearchQuery), где я могу установить критерии для фильтрации данных и EntityDataTable. Последний содержит dataprovider, который может найти DAO для объекта, вызвать метод поиска с параметрами фильтра и создать итератор над ним.
Также существует класс DeleteColumn . Под капотом он проверяет разрешения пользователя для текущего объекта и показывает ссылку ajax.
Я хотел бы пометить его следующим интерфейсом и скрыть его внутри класса DataTable (при необходимости):
public interface HideableColumn<T> {
boolean isCellVisible(T object);
}
Для реализации скрытия я написал следующее:
private List<? extends IColumn<T, String>> allColumns;
@Override
protected void onConfigure() {
super.onConfigure();
if (allColumns == null) allColumns = new ArrayList<>(getColumns());
if (allColumns.stream().anyMatch(e -> e instanceof HideableColumn)) {
getColumns().clear();
Set<T> objects = new HashSet<>();
getDataProvider().iterator(getCurrentPage() * getItemsPerPage(), getItemsPerPage()).forEachRemaining(objects::add); // <-1
allColumns.stream()
.filter(e -> !(e instanceof HideableColumn) || objects.stream().anyMatch(((HideableColumn<T>) e)::isCellVisible))
.forEach(e -> getColumns().add(e)); // <-2
}
}
Но у этого кода есть две проблемы:
1 — это заставляет таблицу дважды вызывать dataProvider#iterator()
2 — он не компилируется из-за того, что DataTable#getColumns() имеет подстановочный знак в объявлении
Ответ №1:
Итак, если все строки в столбце пусты, вы вообще не отображаете столбец?
В этом случае я предлагаю два варианта:
- В калитке: сначала проверьте разрешения и не добавляйте столбец в первую очередь
- В JavaScript: проверьте, пуст ли столбец, и скройте его, вероятно, есть решения для этого в Интернете.
Ответ №2:
Переопределите функцию #onconfigureвашей таблице(), выполните итерацию по всем элементам данных и удалите / добавьте столбец соответствующим образом.
Комментарии:
1. Как я могу получить текущие значения предела и смещения в методе DataTable#onConfigure()?
2. Вы можете использовать DataTable#getItemsPerPage() и #getCurrentPage() .
3. Хорошо, это было бы рабочим решением, но коллекция ‘columns’ в таблице данных объявлена как список с расширенными границами, поэтому в нее невозможно добавить какой-либо элемент. Кроме того, он является окончательным, и я не могу просто установить другую коллекцию вместо существующей.
4. Вы правы. Но ваш код в подклассе или содержащем родительском элементе сохраняет список столбцов без подстановочных знаков по мере необходимости.
5. Это так, но оно не содержит модели данных и строк. Данные загружаются dataProvider, а загрузка данных инициируется таблицей после определения списка столбцов.