vue-vben-admin icon indicating copy to clipboard operation
vue-vben-admin copied to clipboard

能否提供一个自定义封装用户选择框的组件(并托管给Form进行双向绑定管理)

Open accpman opened this issue 4 years ago • 4 comments
trafficstars

⚠️ 重要 ⚠️ 在进一步操作之前,请检查下列选项。如果您忽视此模板或者没有提供关键信息,您的 Issue 将直接被关闭

  • [ ] 已阅读 文档.
  • [ ] 确保您的代码已是最新或者所报告的 Bug 在最新版本中可以重现. (部分 Bug 可能已经在最近的代码中修复)
  • [ ] 已在 Issues 中搜索了相关的关键词
  • [ ] 不是 ant design vue 组件库的 Bug

描述 Bug

我想封装一个自定义选择用户Form组件,单总是提示ReferenceError: Cannot access 'ApiTreeSelect' before initialization如下图 偶尔又不提示组件能用,重启后又提示这个错误组件又不渲染了 效果下图,我必须把弹框界面PositionSelectModal先注释, image

复现 Bug

image image image 问题应是不能在自定义弹框组件中 BasicModal 里用BasicTable 望作者指点下

系统信息

  • 操作系统:
  • Node 版本:
  • 包管理器 (npm/yarn/pnpm) 及其版本:

accpman avatar Sep 01 '21 09:09 accpman

尝试修改代码结构如下:

<template>
  <div class="p-4">
    <BasicTable ref="tableRef" :dataSource="state?.data" @register="registerTable" />
    <PositionSelectModal
      :schemas="positionSelectModalSchemas"
      @register="registerPositionSelectModal"
      @submit="submitPositionSelect"
    />
    <JSelectBizModal
      :schemas="jSelectBizModalSchemas"
      @register="registerJSelectBizModal"
      @submit="submitJSelectBiz"
    />
  </div>
</template>

创建可以动态传参的Modal自定义组件,将JSelectBizModal选择到的数据传入PositionSelectModal即可。 动态传参Modal参考,JSelectBizModal一样采用此类方法封装。

//  Modal
<template>
  <BasicModal v-bind="$attrs" @register="register" :title="title" @ok="getFormValues">
    <BasicForm @register="registerForm" :model="modelRef" />
  </BasicModal>
</template>
<script lang="ts" setup>
  import type { PropType } from 'vue';
  import { ref } from 'vue';
  import { BasicModal, useModalInner } from '/@/components/Modal';
  import { BasicForm, useForm } from '/@/components/Form/index';
  import type { FormSchema } from '/@/components/Form/index';

  const emits = defineEmits(['submit']);
  const props = defineProps({
    title: { type: String, default: '基本信息' },
    schemas: {
      type: [] as PropType<FormSchema[]>,
      default: [
        {
          field: 'data',
          component: 'Input',
          label: '字段',
          defaultValue: 'defaultValue',
        },
      ],
    },
  });
  const modelRef = ref({});
  // 注册Form
  const [
    registerForm,
    {
      validateFields,
      clearValidate,
      resetFields,
      // getFieldsValue, resetFields, setFieldsValue
    },
  ] = useForm({
    labelWidth: 100,
    schemas: props.schemas,
    showActionButtonGroup: false, //重置按钮
    wrapperCol: { span: 16 }, // 输入表格
    // 样式
    baseRowStyle: {
      display: 'flex',
      flexDirection: 'column',
    },
  });
  // 注册Modal
  const [register, { closeModal }] = useModalInner((data: any) => {
    let mergeData: any = {};
    // 动态获取传参
    props.schemas
      .map((item) => item['field'])
      .map((key: string) => {
        if (!data[key]) return;
        return { [key]: data[key] };
      })
      .forEach((item) => {
        mergeData = Object.assign(mergeData, item);
      });
    // 绑定值到form
    modelRef.value = mergeData;
  });
  // 获取表单数据
  async function getFormValues() {
    // 校验表单
    const res = await validateForm();
    // const values = getFieldsValue();
    if (!res) return;
    emits('submit', Object.assign({}, res));
    // 重置校验
    resetValidate();
    // 清除值
    clearField();
    // 关闭 Modal
    closeModal();
  }
  // 校验表格数据
  async function validateForm() {
    try {
      const res = await validateFields();
      console.log('passing', res);
      // 返回校验后数据
      return res;
    } catch (error) {
      return false;
    }
  }
  // 重置表格数据
  async function resetValidate() {
    clearValidate();
  }
  // 清除表格数据
  async function clearField() {
    resetFields();
  }
</script>

frezs avatar Sep 01 '21 15:09 frezs

``

尝试修改代码结构如下:

<template>
  <div class="p-4">
    <BasicTable ref="tableRef" :dataSource="state?.data" @register="registerTable" />
    <PositionSelectModal
      :schemas="positionSelectModalSchemas"
      @register="registerPositionSelectModal"
      @submit="submitPositionSelect"
    />
    <JSelectBizModal
      :schemas="jSelectBizModalSchemas"
      @register="registerJSelectBizModal"
      @submit="submitJSelectBiz"
    />
  </div>
</template>

创建可以动态传参的Modal自定义组件,将JSelectBizModal选择到的数据传入PositionSelectModal即可。 动态传参Modal参考,JSelectBizModal一样采用此类方法封装。

//  Modal
<template>
  <BasicModal v-bind="$attrs" @register="register" :title="title" @ok="getFormValues">
    <BasicForm @register="registerForm" :model="modelRef" />
  </BasicModal>
</template>
<script lang="ts" setup>
  import type { PropType } from 'vue';
  import { ref } from 'vue';
  import { BasicModal, useModalInner } from '/@/components/Modal';
  import { BasicForm, useForm } from '/@/components/Form/index';
  import type { FormSchema } from '/@/components/Form/index';

  const emits = defineEmits(['submit']);
  const props = defineProps({
    title: { type: String, default: '基本信息' },
    schemas: {
      type: [] as PropType<FormSchema[]>,
      default: [
        {
          field: 'data',
          component: 'Input',
          label: '字段',
          defaultValue: 'defaultValue',
        },
      ],
    },
  });
  const modelRef = ref({});
  // 注册Form
  const [
    registerForm,
    {
      validateFields,
      clearValidate,
      resetFields,
      // getFieldsValue, resetFields, setFieldsValue
    },
  ] = useForm({
    labelWidth: 100,
    schemas: props.schemas,
    showActionButtonGroup: false, //重置按钮
    wrapperCol: { span: 16 }, // 输入表格
    // 样式
    baseRowStyle: {
      display: 'flex',
      flexDirection: 'column',
    },
  });
  // 注册Modal
  const [register, { closeModal }] = useModalInner((data: any) => {
    let mergeData: any = {};
    // 动态获取传参
    props.schemas
      .map((item) => item['field'])
      .map((key: string) => {
        if (!data[key]) return;
        return { [key]: data[key] };
      })
      .forEach((item) => {
        mergeData = Object.assign(mergeData, item);
      });
    // 绑定值到form
    modelRef.value = mergeData;
  });
  // 获取表单数据
  async function getFormValues() {
    // 校验表单
    const res = await validateForm();
    // const values = getFieldsValue();
    if (!res) return;
    emits('submit', Object.assign({}, res));
    // 重置校验
    resetValidate();
    // 清除值
    clearField();
    // 关闭 Modal
    closeModal();
  }
  // 校验表格数据
  async function validateForm() {
    try {
      const res = await validateFields();
      console.log('passing', res);
      // 返回校验后数据
      return res;
    } catch (error) {
      return false;
    }
  }
  // 重置表格数据
  async function resetValidate() {
    clearValidate();
  }
  // 清除表格数据
  async function clearField() {
    resetFields();
  }
</script>

不是很理解,PositionSelectModal 是具体的选择框是个列表,选择数据后要回传给JSelectBiz ,JSelectBiz封装了一个下拉框和一个选择按钮,JSelectBiz作为自定义组件注册给了BasicForm

accpman avatar Sep 02 '21 01:09 accpman

你position的选择应该是用了basic-table把? basic-table里面又使用了form,那你这个form里面又使用了basic-table,block住了

hyperq avatar Nov 08 '21 05:11 hyperq

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days

anncwb avatar May 12 '24 01:05 anncwb