alibaba / formily

📱🚀 🧩 Cross Device & High Performance Normal Form/Dynamic(JSON Schema) Form/Form Builder -- Support React/React Native/Vue 2/Vue 3
https://formilyjs.org/
MIT License
11.12k stars 1.44k forks source link

[Feature Request] ArrayBase.Remove/Copy/MoveUp/MoveDown 组件支持禁用默认行为 #3977

Closed whinc closed 9 months ago

whinc commented 10 months ago

What problem does this feature solve?

ArrayBase的衍生组件包括ArrayCards/ArrayCollpase/ArrayItems/ArrayTable/ArrayTabs,它们都包含Remove/Copy/MoveUp/MoveDown 内置组件,这些内置组件的点击事件无法禁用默认行为,导致无法满足一些场景的需求,例如禁用特定行的操作、根据条件禁用特定行的操作等,目前暂时的解决办法是自定义组件改写 Remove/Copy/MoveUp/MoveDown 的内部实现,这些内置组件使用比较高频,且内置组件支持该场景很容易,且无API破坏,放在内置组件中会更好。

What does the proposed API look like?

实现方式1

提意将 ArrayBase 内部的 Remove/Copy/MoveUp/MoveDown的 onClick 事件实现进行如下调整,onClick 如果调用了 event.preventDefault()后就不再执行默认的行为

ArrayBase.Remove = React.forwardRef((props, ref) => {
  // ...
  return (
    <Button
     {/* ... */}
      ref={ref}
      onClick={(e) => {
        if (self?.disabled) return
        e.stopPropagation()
-       array.field?.remove?.(index)
-       array.props?.onRemove?.(index)
-       if (props.onClick) {
-         props.onClick(e)
-       }

+       if (props.onClick) {
+         props.onClick(e)
+        if (e.defaultPrevented) return
+       }
+       array.field?.remove?.(index)
+       array.props?.onRemove?.(index)
      }}
      icon={isUndef(props.icon) ? <DeleteOutlined /> : props.icon}
    >
      {props.title || self.title}
    </Button>
  )
})

用户代码侧可通过如下方式来重写这些内置操作的默认行为

<SchemaField schema={{
// ...
                properties: {
                  remove: {
                    type: 'void',
                    'x-component': 'ArrayTable.Remove',
                    'x-component-props': {
                        onClick: (e) => {
                            // 禁用默认行为
                            e.preventDefault()   
                            console.log('click Remove')
                        }
                    }
                  },
// ...
}} />

实现方式2

ArrayBase 内部的 Remove/Copy/MoveUp/MoveDown 增加单独属性来禁用默认行为,如 disableDefaultBehaivor

ArrayBase.Remove = React.forwardRef((props, ref) => {
  // ...
  return (
    <Button
     {/* ... */}
      onClick={(e) => {
        if (self?.disabled) return
        e.stopPropagation()
-        array.field?.remove?.(index)
-        array.props?.onRemove?.(index)
+       if (!props.disableDefaultBehavior?.(index))  {
+         array.field?.remove?.(index)
+         array.props?.onRemove?.(index)
+       }
        if (props.onClick) {
          props.onClick(e)
        }
      }}
      icon={isUndef(props.icon) ? <DeleteOutlined /> : props.icon}
    >
      {props.title || self.title}
    </Button>
  )
})

用户代码侧可通过如下方式来重写这些内置操作的默认行为

<SchemaField schema={{
// ...
                properties: {
                  remove: {
                    type: 'void',
                    'x-component': 'ArrayTable.Remove',
                    'x-component-props': {
                        // 禁用默认行为
                        disableDefaultBehavior: index => index % 2 === 0,
                        onClick: (e) => {
                            console.log('click Remove')
                        }
                    }
// ...
}} />
whinc commented 10 months ago

如果提议能通过,我非常乐意提 PR 来实现这一特性

janryWang commented 9 months ago

倾向于方案1哈,感谢PR

whinc commented 9 months ago

倾向于方案1哈,感谢PR

好的👌,我将会尽快实现并PR

whinc commented 9 months ago

倾向于方案1哈,感谢PR

已提了 PR https://github.com/alibaba/formily/pull/3998