Sulu CMF - 将参数传递给 FormOverlayList 添加表单中的自动完成字段

Sulu CMF - Pass parameter to autocomplete field in FormOverlayList add form

这个问题是followup.

我有两个实体 DataSetDataGroup

class DataSet {
  string $name;
  Collection $groups; // Collection<int, DataGroup>
}
class DataGroup {
  string $name;
  DataSet $dataSet;
  ?DataGroup $nextGroup; // Condition: $nextGroup !== $this && $nextGroup->dataSet === $this->dataSet
}

属性 DataGroup::nextGroup 可以引用任何 其他 DataGroup 与同一 DataSet 关联的实体].

我想创建一个 CRUD 表单,我可以在其中添加、编辑和删除 DataSet 个实体。在这个 DataSet 表单中,我还想包含一个选项卡,我可以在其中对与当前 DataSet.

关联的实体进行 CRUD DataGroup

我创建了列表元数据 data_sets.xmldata_groups.xml,以及表单元数据 data_set.xmldata_group.xml

<!-- lists/data_sets.xml -->
<list xmlns="http://schemas.sulu.io/list-builder/list">
  <key>data_sets</key>
  <properties>
    <property name="name" visibility="always" searchability="yes">
      <field-name>name</field-name>
      <entity-name>App\Entity\DataSet</entity-name>
    </property>
  </properties>
</list>

<!-- lists/data_groups.xml -->
<list xmlns="http://schemas.sulu.io/list-builder/list">
  <key>data_groups</key>
  <properties>
    <property name="name" visibility="always" searchability="yes">
      <field-name>name</field-name>
      <entity-name>App\Entity\DataSet</entity-name>
    </property>
    <property name="dataSet" visibility="always">
      <field-name>name</field-name>
      <entity-name>App\Entity\DataSet</entity-name>
      <joins>
        <join>
          <entity-name>App\Entity\DataSet</entity-name>
          <field-name>App\Entity\DataGroup.dataSet</field-name>
        </join>
      </joins>
    </property>
  </properties>
</list>
<!-- forms/data_set.xml -->
<form xmlns="http://schemas.sulu.io/template/template"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://schemas.sulu.io/template/template 
      http://schemas.sulu.io/template/form-1.0.xsd"
>
  <key>data_set</key>
  <properties>
    <property name="name" type="text_line" mandatory="true">
      <params>
        <param name="headline" value="true"/>
      </params>
    </property>
  </properties>
</form>

<!-- forms/data_group.xml -->
<form xmlns="http://schemas.sulu.io/template/template"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://schemas.sulu.io/template/template 
      http://schemas.sulu.io/template/form-1.0.xsd"
>
  <key>data_group</key>
  <properties>
    <property name="name" type="text_line" mandatory="true">
      <params>
        <param name="headline" value="true"/>
      </params>
    </property>
    <property name="nextGroup" type="single_data_group_selection">
      <params>
        <param name="type" value="auto_complete"/>
        <param name="resource_store_properties_to_request" type="collection">
          <param name="dataSetId" value="id"/>
        </param>
      </params>
    </property>
  </properties>
</form>

我还为 REST 路由和自定义单选配置了 sulu_admin.yaml

sulu_admin:
  resources:
    data_sets:
      routes:
        list: app.get_data_sets
        detail: app.get_data_set
    data_groups:
      routes:
        list: app.get_data_groups
        details: app.get_data_group
  field_type_options:
    single_selection:
      single_data_group_selection:
        default_type: 'auto_complete'
        resource_key: 'data_groups'
        types:
          auto_complete:
            display_property: 'name'
            search_properties:
              - 'name'

我为两个实体实现了两个 REST 控制器。 DataSetController 是从 Docs 开始构建的,而 DataGroupController 对列表路由有一个小的扩展:

class DataGroupController implements ClassResourceInterface
{
  public function cgetAction(int $dataSetId, Request $request): Response
  {
    // ... Init field descriptors and execute listBuilder
    
    $list = new ListRepresentation(
      $listResponse,
      'data_groups',
      \array_merge(['dataSetId' => $dataSetId], $request->query->all()), // add DataSet ID
      $listBuilder->getCurrentPage(),
      $listBuilder->getLimit(),
      $listBuilder->count()
    );

    // ... handle view
  }

  // ...
}

最后,我实现了自定义管理 class,如 Docs 中所述。

class DataAdmin extends Admin
{
  public const DATA_SET_DETAILS = 'data_set_details';
  public const DATA_SET_GROUPS = 'data_set_groups';
  public const DATA_SET_LIST = 'app.data_sets_list';
  public const DATA_SET_ADD_FORM = 'app.data_set_add_form';
  public const DATA_SET_ADD_FORM_DETAILS = 'app.data_set_add_form.details';
  public const DATA_SET_EDIT_FORM = 'app.data_set_edit_form';
  public const DATA_SET_EDIT_FORM_DETAILS = 'app.data_set_edit_form.details';
  public const DATA_SET_EDIT_FORM_GROUPS = 'app.data_set_edit_form.groups';

  public function configureViews(ViewCollection $viewCollection): void
  {
    // Add DataSet list view
    // Add DataSet add form view
    // Add DataSet edit form view (details)
    
    /*
     * Custom second DataSet edit form tab for DataGroup CRUDding
     */
    $groupsFormOverlayList = $this->viewBuilderFactory
      ->createFormOverlayListViewBuilder(self::DATA_SET_EDIT_FORM_GROUPS, '/groups')
      ->setResourceKey(self::DATA_SET_GROUPS)
      ->setListKey(self::DATA_SET_GROUPS)
      ->addListAdapters(['table'])
      ->addRouterAttributesToListRequest(['id' => 'dataSetId'])
      ->setFormKey(self::DATA_SET_GROUPS)
      ->addRouterAttributesToFormRequest(['id' => 'dataSetId'])
      ->setTabTitle('app.data_groups')
      ->addToolbarActions([
        new ToolbarAction('sulu_admin.add'),
        new ToolbarAction('sulu_admin.delete')
      ])
    ;
    $viewCollection->add($groupsFormOverlayList->setParent(self::DATA_SET_EDIT_FORM));
  }
}

截至目前

尝试添加新的 DataGroup 时,我无法对 nextGroup 执行自动完成搜索,因为 dataSetId 参数是 而不是 传递给字段,禁止 ResourceRequester 执行 REST 请求。

如何将 dataSetId 传递给“新 DataGroup”表单的字段以便仅搜索匹配的实体?

非常感谢您的详细描述!不幸的是,目前使用内置的自动完成组件恐怕无法实现您正在尝试做的事情。

resource_store_properties_to_request 参数从呈现自动完成组件的表单数据中读取值。如果您正在创建一个新的 DataGroup 实体,表单的数据是空的(因为现在有新实体的现有数据)因此 resource_store_properties_to_request 参数无法读取 dataSetId值。

很抱歉,但我认为您需要实现自定义自动完成字段类型,从当前 url 中读取 dataSetId 值以实现所需的功能。如果您有兴趣这样做,我建议您查看 basic field-type example in the sulu-demo repository.