Scaffold ListBox множественный выбор в ModelAdmin Filter для DataObject с Enum

В настоящее время автоматические леса для полей поиска, в которых есть перечисление, дают раскрывающийся список, позволяющий сделать только один выбор. Я заинтересован в использовании существующих фильтров, чтобы изменить это, чтобы разрешить множественный выбор.

Учитывая следующие данные объекта …

class MyDataObject extends DataObject {
static $db = array(
'Name'      => "Varchar(255)",
'MyEnum'    => "Enum('Option1,Option2,Option3','Option1')");
}

…и следующий ModelAdmin …

class MyModelAdmin extends ModelAdmin {
static $mangaged_models = array(
'MyDataObject',
);
static $url_segment = 'mymodeladmin';
static $menu_title = 'MyModelAdmin';
static $menu_priority = 9;
}

…Я ищу модуль или какой-то простой фильтр, чтобы выложить Enum в список множественного выбора.

список множественного выбора определяется как …

  • Позволяет множественный выбор
  • После ввода некоторых символов предлагаются предложения

И я прошу общий решение — я могу построить контекст поиска для каждой модели администратора, но это очень расстраивает.
Примерно следующее с использованием либо существующего фильтра (ExactMatchMultiFilter выглядит идеально, но на самом деле не выглядит Работа) или, если таковой имеется в модуле, или кто-то может предложить, как изменить существующий фильтр для этого, это было бы замечательно.

class MyDataObject extends DataObject {
static $db = array(
'Name'      => "Varchar(255)",
'MyEnum'    => "Enum('Option1,Option2,Option3','Option1')");
public static $searchable_fields = array (
'MyEnum'    => array('filter' => 'ExactMatchMultiFilter')
);
}

Буду признателен за любую оказанную помощь.

4

Решение

От вашего вопроса, кажется, вы хотели, чтобы filter если вы перейдете в поле поиска, это поменяет строительные леса. Я немного покопался, но, похоже, это не так. Однако, если вы использовали field вариант вместо этого, вы, вероятно, можете достичь того, что вы хотите.

Вы специально упоминаете ListboxField и хотя он поддерживает несколько, он не включен конструктором по умолчанию на поле как это было бы реализовано.

То, что вы хотите, может быть достигнуто из коробки немного больше
CheckboxSetField. (Я признаю, пользовательский интерфейс немного средний, когда используется в ModelAdmin)

Полученный код может выглядеть примерно так:

class MyDataObject extends DataObject {
static $db = array(
'Name'      => "Varchar(255)",
'MyEnum'    => "Enum('Option1,Option2,Option3','Option1')");
public static $searchable_fields = array (
'MyEnum'    => array('field' => 'CheckboxSetField')
);
}

К сожалению, это не так просто, вы заметите, просто сделав так, что вместо списка флажков появится «Нет доступных вариантов». Это связано с тем, что SilverStripe действует иначе, когда мы предоставляем field вариант, который я упоминал ранее.

Обходной путь для такого не велик, но, возможно, все еще универсален. Я сделал расширение класса ModelAdminэто выглядит для CheckboxSetField в форме поиска и устанавливает для него значения Enum.

class MyModelAdminExtension extends Extension {
public function updateSearchForm($form) {

$modelClass = $form->getController()->modelClass;

foreach ($form->Fields() as $field) {
if ($field->class == 'CheckboxSetField') {
//We need to remove the "q[]" around the field name set by ModelAdmin
$fieldName = substr($field->getName(), 2, -1);
$dbObj = singleton($modelClass)->dbObject($fieldName);
if ($dbObj->class == 'Enum') {
$enumValues = $dbObj->enumValues();
$field->setSource($enumValues);
}
}
}
}
}

Это относительно безопасно ModelAdmin расширение, поскольку оно специально ищет комбинацию Enum, сопоставленной с CheckboxSetField что может произойти, только если вы укажете это вручную.

Зайдя так далеко, мы могли бы оглянуться назад на ListboxFieldПреодолеть отключенную опцию множественного выбора и заполнить ее значениями (так как при этом возникает та же проблема, что и выше) Это решение будет немного менее общим, так как мы заставим все ListboxFieldЭто были сопоставлены из Enum, чтобы быть кратными, но если мы хотим более хорошее решение, это то, как мы можем его получить.

class MyModelAdminExtension extends Extension {
public function updateSearchForm($form) {

$modelClass = $form->getController()->modelClass;

foreach ($form->Fields() as $field) {
if ($field->class == 'ListboxField') {
//We need to remove the "q[]" around the field name set by ModelAdmin
$fieldName = substr($field->getName(), 2, -1);
$dbObj = singleton($modelClass)->dbObject($fieldName);
if ($dbObj->class == 'Enum') {
$field->setMultiple(true);

$enumValues = $dbObj->enumValues();
$field->setSource($enumValues);
}
}
}
}
}

И для нашей модели …

class MyDataObject extends DataObject {

private static $db = array(
'Name' => "Varchar(255)",
'MyEnum' => "Enum('Option1,Option2,Option3','Option1')");

public static $searchable_fields = array (
'MyEnum' => array('field' => 'ListboxField')
);
}

Теперь у вас есть то, что вы хотели — мульти-выбор ListBoxField со значениями Enum.

Вы можете спросить сейчас, почему я покрыл CheckboxSetField? Ну, я думаю, что важно посмотреть на все возможные решения. Я пришел к решению, которое я предоставил, попробовав CheckboxSetField и это действительно было только в последнюю минуту, когда я понял, с некоторыми незначительными изменениями, я мог заставить его работать на ListboxField,


Как вы уже говорили, существует проблема для кода выше, обрабатывающего Enum через HasOne отношения. Это связано с ModelAdmin расширение принимает имя поля и обрабатывает его исключительно как поле базы данных (через dbObject) на модельный класс формы. Вместо этого мы можем обнаружить отношение по двойному подчеркиванию имени поля, заменив его точечным синтаксисом и обработав его вместо отношения (через relObject).

Наш обновленный updateSearchForm функция будет выглядеть так:

public function updateSearchForm($form) {

$modelClass = $form->getController()->modelClass;

foreach ($form->Fields() as $field) {
if ($field->class == 'ListboxField') {
//We need to remove the "q[]" around the field name set by Model Admin
$fieldName = substr($field->getName(), 2, -1);
$dbObj = null;

//Check if the field name represents a value across a relationship
if (strpos($fieldName, '__') !== false) {
//To use "relObject", we need dot-syntax
$fieldName = str_replace('__', '.', $fieldName);
$dbObj = singleton($modelClass)->relObject($fieldName);
}
else {
$dbObj = singleton($modelClass)->dbObject($fieldName);
}

if ($dbObj != null && $dbObj->class == 'Enum') {
$field->setMultiple(true);

$enumValues = $dbObj->enumValues();
$field->setSource($enumValues);
}
}
}
}
3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]