diff --git a/src/components/HasManyFields/HasManyFields.d.ts b/src/components/HasManyFields/HasManyFields.d.ts
index 4d28209c2..1e09c672b 100644
--- a/src/components/HasManyFields/HasManyFields.d.ts
+++ b/src/components/HasManyFields/HasManyFields.d.ts
@@ -16,6 +16,8 @@ interface HasManyFieldsPropTypes {
minimumRows?: number;
maximumRows?: number;
reorderable?: boolean;
+ dragHandle?: 'outside' | 'inside';
+ rowClassName?: string;
value?: HasManyValue[];
className?: string;
}
diff --git a/src/components/HasManyFields/HasManyFields.js b/src/components/HasManyFields/HasManyFields.js
index deea2f634..fc634703c 100644
--- a/src/components/HasManyFields/HasManyFields.js
+++ b/src/components/HasManyFields/HasManyFields.js
@@ -9,15 +9,22 @@ import HasManyFieldsRow from './HasManyFieldsRow';
const DragHandler = withDragHandler();
-const SortableItem = ReorderableElement(({ key, sortIndex, value, renderHasManyFieldsRow }) => (
-
{value.map((item, index) => (
))}
@@ -44,6 +52,7 @@ class HasManyFields extends React.Component {
minimumRows: 1,
maximumRows: Infinity,
reorderable: false,
+ dragHandle: 'outside',
};
constructor(props) {
@@ -135,32 +144,53 @@ class HasManyFields extends React.Component {
return isFunction && !(Template.prototype && Template.prototype.render);
};
- renderHasManyFieldsRow = (key, index, value) => {
- const { template: Template, disabled, deleteProps, errors, minimumRows } = this.props;
+ renderHasManyFieldsRow = (key, index, value, dragHandle) => {
+ const {
+ template: Template,
+ disabled,
+ deleteProps,
+ errors,
+ minimumRows,
+ rowClassName,
+ } = this.props;
const refProps = this.isStateless(Template) ? {} : { ref: this.setRowReference(index) };
+ const template = (
+
+ );
+
return (
minimumRows}
disabled={disabled}
deleteProps={deleteProps}
>
-
+ {dragHandle ? (
+
+ {dragHandle}
+
+ {template}
+
+
+ ) : (
+ template
+ )}
);
};
render() {
- const { className, disabled, reorderable } = this.props;
+ const { className, disabled, reorderable, dragHandle } = this.props;
if (!disabled && reorderable) {
return (
@@ -172,6 +202,7 @@ class HasManyFields extends React.Component {
useDragHandle
lockAxis="y"
value={this.value}
+ dragHandleInside={dragHandle === 'inside'}
renderHasManyFieldsRow={this.renderHasManyFieldsRow}
renderAddRow={this.renderAddRow}
/>
diff --git a/src/components/HasManyFields/HasManyFields.spec.js b/src/components/HasManyFields/HasManyFields.spec.js
index d76bc3219..a12b167bb 100644
--- a/src/components/HasManyFields/HasManyFields.spec.js
+++ b/src/components/HasManyFields/HasManyFields.spec.js
@@ -274,6 +274,50 @@ describe('
', () => {
assert.equal(items.length, component.find('.js-reorderable-item').length);
assert.equal(items.length, component.find(HasManyFieldsRow).length);
});
+
+ it('renders drag handles outside the rows by default', () => {
+ assert.equal(items.length, component.find('div.rg-DragHandler').length);
+ assert.equal(0, component.find(HasManyFieldsRow).at(0).find('div.rg-DragHandler').length);
+ });
+ });
+ });
+
+ describe('reorderable with dragHandle="inside"', () => {
+ let component;
+
+ beforeEach(() => {
+ component = mount(
+
+ );
+ });
+
+ it('has correct number of reorderable items', () => {
+ assert.equal(items.length, component.find('.js-reorderable-item').length);
+ assert.equal(items.length, component.find(HasManyFieldsRow).length);
+ });
+
+ it('renders each drag handle inside its row', () => {
+ component.find(HasManyFieldsRow).forEach((row) => {
+ assert.equal(1, row.find('div.rg-DragHandler').length);
+ });
+ });
+ });
+
+ it('passes rowClassName through to each row', () => {
+ const component = mount(
+
+ );
+
+ component.find(HasManyFieldsRow).forEach((row) => {
+ assert.equal('border rounded p-3', row.prop('className'));
});
});
});
diff --git a/src/components/HasManyFields/HasManyFields.stories.js b/src/components/HasManyFields/HasManyFields.stories.js
index b34ddf832..f5b185fd8 100644
--- a/src/components/HasManyFields/HasManyFields.stories.js
+++ b/src/components/HasManyFields/HasManyFields.stories.js
@@ -66,6 +66,14 @@ LiveExample.args = {
minimumRows: 1,
maximumRows: 5,
reorderable: false,
+ dragHandle: 'outside',
+ rowClassName: '',
+};
+LiveExample.argTypes = {
+ dragHandle: {
+ control: 'radio',
+ options: ['outside', 'inside'],
+ },
};
export const RowWrapper = (args) => (