baidu / amis

前端低代码框架,通过 JSON 配置就能生成各种页面。
https://baidu.github.io/amis/
Apache License 2.0
17.44k stars 2.53k forks source link

给自定义组件setValue无效 #9101

Open africa1207 opened 11 months ago

africa1207 commented 11 months ago

描述问题:

下拉框更改值以后,用selectedItems中字段给其他组件赋值,amis自带组件能赋值成功,但是自定义组件赋值失败,而且会导致下拉框显示问题,自定义组件使用FormItem注解

截图或视频:

2023-12-11_15-37-30

如何复现(请务必完整填写下面内容):

  1. 你是如何使用 amis 的? npm

  2. amis 版本是什么?

    "amis": "^3.4.1",
    "amis-formula": "^3.4.1",
  3. 粘贴有问题的完整 amis schema 代码:

    
    // schema代码
    {
    type: 'page',
    body: [
    {
      type: 'form',
      body: [
        {
          type: 'select',
          label: '下拉框',
          name: 'select',
          id: 'select',
          multiple: false,
          options: [
            {
              label: '测试内容',
              value: '1',
              default_amount: '100',
              custom_attach_file: [
                { name: '文件1', id: '1', size: 10000, url: 'http://www.baidu.com' },
              ],
              custom_input_value: 'custom_input_value',
            },
          ],
          onEvent: {
            change: {
              weight: 0,
              actions: [
                {
                  componentId: 'default_amount',
                  ignoreError: false,
                  actionType: 'setValue',
                  args: {
                    value: '${event.data.selectedItems.default_amount}',
                  },
                },
                {
                  componentId: 'custom_attach_file',
                  ignoreError: false,
                  actionType: 'setValue',
                  args: {
                    value: '${event.data.selectedItems.custom_attach_file}',
                  },
                },
                {
                  componentId: 'custom_input_value',
                  ignoreError: false,
                  actionType: 'setValue',
                  args: {
                    value: '${event.data.selectedItems.custom_input_value}',
                  },
                },
              ],
            },
          },
        },
        {
          type: 'custom-input',
          label: '自定义input',
          name: 'custom_input_value',
          id: 'custom_input_value',
          keyboard: true,
        },
        {
          type: 'custom-upload',
          label: '自定义上传',
          name: 'custom_attach_file',
          id: 'custom_attach_file',
          disabled: false,
        },
        {
          type: 'input-number',
          label: '默认组件',
          name: 'default_amount',
          id: 'default_amount',
          keyboard: true,
          step: 1,
          static: true,
        },
      ],
      actions: [],
    },
    ],
    }

// custom-input代码 import { FormItem } from 'amis'; import { FormItemProps } from 'amis'; import React from 'react'; import { Input } from 'antd';

export type CustomInputProps = FormItemProps;

export default FormItem({ type: 'custom-input', // strictMode: false, autoVar: true, })( class CustomInput extends React.Component { static defaultProps = {};

render() {
  const { value, onChange, placeholder, maxLength, ...rest } = this.props;
  function onValueChange(event) {
    onChange(event.target.value);
  }
  return (
    <div>
      <Input
        value={value}
        onChange={onValueChange}
        placeholder={placeholder}
        maxLength={maxLength}
      />
    </div>
  );
}

} as any, );

allenve commented 11 months ago

自定义组件中需要监听对应事件 参考 https://aisuda.bce.baidu.com/amis/zh-CN/docs/concepts/event-action#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BB%84%E4%BB%B6%E6%8E%A5%E5%85%A5%E4%BA%8B%E4%BB%B6%E5%8A%A8%E4%BD%9C

africa1207 commented 11 months ago

自定义组件中需要监听对应事件 参考 https://aisuda.bce.baidu.com/amis/zh-CN/docs/concepts/event-action#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BB%84%E4%BB%B6%E6%8E%A5%E5%85%A5%E4%BA%8B%E4%BB%B6%E5%8A%A8%E4%BD%9C 没有理解到,我只是需要给自定义组件赋值,不需要外部调用自定义组件的方法,能否给个demo呢?

allenve commented 11 months ago

https://github.com/baidu/amis/blob/master/packages/amis/src/renderers/Form/InputText.tsx#L266 参考这里代码的实现 组件内部需要监听派发的事件然后实现更新操作

ityue commented 11 months ago

楼主实现给自定义组件setValue生效了吗?刚试了下按楼上回答的加上doAction,拦截不到actionType

allenve commented 11 months ago

不仅需要加上 doAction 还需要注册 第一个发的文档那里有个组件通信: https://aisuda.bce.baidu.com/amis/zh-CN/docs/extend/custom-react#%E7%BB%84%E4%BB%B6%E9%97%B4%E9%80%9A%E4%BF%A1

africa1207 commented 11 months ago

不仅需要加上 doAction 还需要注册 第一个发的文档那里有个组件通信: https://aisuda.bce.baidu.com/amis/zh-CN/docs/extend/custom-react#%E7%BB%84%E4%BB%B6%E9%97%B4%E9%80%9A%E4%BF%A1

如果自定义组件是使用函数式组件实现的,如何内部添加doAction,并且注册自己呢?我看代码都是类组件来实现的

allenve commented 11 months ago

上面地址就是示例代码呀

import * as React from 'react';
import {Renderer, ScopedContext} from 'amis';
@Renderer({
  type: 'my-renderer'
})
export class CustomRenderer extends React.Component {
  static contextType = ScopedContext;

  constructor() {
    const scoped = this.context;
    scoped.registerComponent(this);
  }

  componentWillUnmount() {
    const scoped = this.context;
    scoped.unRegisterComponent(this);
  }

  // 其他部分省略了。
}
africa1207 commented 11 months ago

上面地址就是示例代码呀

import * as React from 'react';
import {Renderer, ScopedContext} from 'amis';
@Renderer({
  type: 'my-renderer'
})
export class CustomRenderer extends React.Component {
  static contextType = ScopedContext;

  constructor() {
    const scoped = this.context;
    scoped.registerComponent(this);
  }

  componentWillUnmount() {
    const scoped = this.context;
    scoped.unRegisterComponent(this);
  }

  // 其他部分省略了。
}

不是,我的意思是我自定义组件没使用类组件,使用了函数式组件和hook,那函数式组件如何实现内部添加doAction,并且注册自己?代码示例看到的都是类组件实现方式

allenve commented 11 months ago

https://github.com/baidu/amis/blob/master/packages/amis-core/src/Scoped.tsx#L84 这块核心是用的 createContext 函数组件中能获取到 但是注册不了 所以只能在函数组件外层包一个class组件

taoyao-code commented 11 months ago

请问有解决方案吗?

ityue commented 11 months ago

使用上面说的 scoped.registerComponent,自定义组件使用的FormItem注册的,但doAction还是接收不到信息,请问doAction是接收onEvent里面的事件吗

cheungzh commented 3 weeks ago

自定义组件中需要监听对应事件 参考 https://aisuda.bce.baidu.com/amis/zh-CN/docs/concepts/event-action#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BB%84%E4%BB%B6%E6%8E%A5%E5%85%A5%E4%BA%8B%E4%BB%B6%E5%8A%A8%E4%BD%9C

class组件可以 doaction 函数式组件好像不太行