Skip to content

Commit

Permalink
feat: added duplicate button to repeatArrayField
Browse files Browse the repository at this point in the history
  • Loading branch information
dereekb committed Nov 25, 2022
1 parent 467a879 commit f4e027b
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ export class DocFormValueComponent {
}),
repeatArrayField({
key: 'test2',
label: 'Field With Add and Remove Diabled',
label: 'Field With Add and Remove Diabled Via Field',
description: 'Shows the remove button being disabled when a value is a certain value, and shows the duplicate button.',
duplicateText: 'Make Copy',
repeatFieldGroup: [
nameField(),
toggleField({
Expand All @@ -106,8 +108,10 @@ export class DocFormValueComponent {
],
disableRearrange: true,
allowAdd: true,
allowDuplicate: true,
allowRemove: ({ i, value }) => !(value as { disable: boolean }).disable,
labelForField: ({ value }) => (value as { name: string }).name
labelForField: ({ value }) => (value as { name: string }).name,
addDuplicateToEnd: true
})
];

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CdkDragDrop } from '@angular/cdk/drag-drop';
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, TrackByFunction } from '@angular/core';
import { asDecisionFunction, asGetter, cachedGetter, DecisionFunction, FactoryWithInput, FactoryWithRequiredInput, Getter, getValueFromGetter, IndexRef, makeGetter, Maybe } from '@dereekb/util';
import { FieldArrayTypeConfig, FieldArrayType, FormlyFieldConfig, FormlyFieldProps } from '@ngx-formly/core';

Expand All @@ -17,6 +17,10 @@ export interface DbxFormRepeatArrayConfig<T = unknown> extends Pick<FormlyFieldP
* Text for the add button.
*/
addText?: string;
/**
* Text for the duplicate button.
*/
duplicateText?: string;
/**
* Text for the remove button.
*/
Expand All @@ -33,10 +37,18 @@ export interface DbxFormRepeatArrayConfig<T = unknown> extends Pick<FormlyFieldP
* True by default.
*/
allowAdd?: boolean;
/**
* Whether or not to allow duplicateing items. Can optionally pass a decision function that decides whether or not a specific item can be removed.
*/
allowDuplicate?: boolean | DecisionFunction<DbxFormRepeatArrayPair<T>>;
/**
* Whether or not to allow removing items. Can optionally pass a decision function that decides whether or not a specific item can be removed.
*/
allowRemove?: boolean | DecisionFunction<DbxFormRepeatArrayPair<T>>;
/**
* Adds the duplicate to the end of the values
*/
addDuplicateToEnd?: boolean;
}

@Component({
Expand All @@ -45,7 +57,7 @@ export interface DbxFormRepeatArrayConfig<T = unknown> extends Pick<FormlyFieldP
<dbx-subsection [header]="label" [hint]="description">
<!-- Fields -->
<div class="dbx-form-repeat-array-fields" cdkDropList [cdkDropListDisabled]="disableRearrange" (cdkDropListDropped)="drop($event)">
<div class="dbx-form-repeat-array-field" cdkDrag cdkDragLockAxis="y" *ngFor="let field of field.fieldGroup; let i = index; let last = last">
<div class="dbx-form-repeat-array-field" cdkDrag cdkDragLockAxis="y" *ngFor="let field of field.fieldGroup; trackBy: trackByFunction; let i = index; let last = last">
<div class="dbx-form-repeat-array-drag-placeholder" *cdkDragPlaceholder></div>
<dbx-bar class="dbx-bar-fixed-height">
<button *ngIf="!disableRearrange" cdkDragHandle mat-flat-button><mat-icon>drag_handle</mat-icon></button>
Expand All @@ -55,6 +67,7 @@ export interface DbxFormRepeatArrayConfig<T = unknown> extends Pick<FormlyFieldP
<span>{{ labelForItem(field, i) }}</span>
</h4>
<span class="dbx-spacer"></span>
<dbx-button *ngIf="allowDuplicate(i)" [text]="duplicateText" (buttonClick)="duplicate(i)"></dbx-button>
<dbx-button *ngIf="allowRemove(i)" color="warn" [text]="removeText" (buttonClick)="remove(i)"></dbx-button>
</dbx-bar>
<formly-field class="dbx-form-repeat-array-field-content" [field]="field"></formly-field>
Expand Down Expand Up @@ -83,6 +96,10 @@ export class DbxFormRepeatArrayTypeComponent<T = unknown> extends FieldArrayType
return asDecisionFunction(this.field.props.allowRemove, true);
});

private _allowDuplicate: Getter<DecisionFunction<DbxFormRepeatArrayPair<T>>> = cachedGetter(() => {
return asDecisionFunction(this.field.props.allowDuplicate || false, false);
});

get repeatArrayField(): DbxFormRepeatArrayConfig {
return this.field.props;
}
Expand All @@ -95,6 +112,10 @@ export class DbxFormRepeatArrayTypeComponent<T = unknown> extends FieldArrayType
return this.field.props.description;
}

get duplicateText(): string {
return this.repeatArrayField.addText ?? 'Duplicate';
}

get addText(): string {
return this.repeatArrayField.addText ?? 'Add';
}
Expand All @@ -119,6 +140,10 @@ export class DbxFormRepeatArrayTypeComponent<T = unknown> extends FieldArrayType
return this.field.props.allowAdd ?? true;
}

get addDuplicateToEnd(): boolean {
return this.field.props.addDuplicateToEnd ?? false;
}

allowRemove(i: number) {
const array: unknown[] = this.model;
const value = array[i] as T;
Expand All @@ -128,6 +153,15 @@ export class DbxFormRepeatArrayTypeComponent<T = unknown> extends FieldArrayType
});
}

allowDuplicate(i: number) {
const array: unknown[] = this.model;
const value = array[i] as T;
return this._allowDuplicate()({
i,
value
});
}

get addItemDisabled() {
return !this.canAddItem;
}
Expand All @@ -142,6 +176,10 @@ export class DbxFormRepeatArrayTypeComponent<T = unknown> extends FieldArrayType
}
}

readonly trackByFunction: TrackByFunction<FormlyFieldConfig> = (i, x) => {
return x.key;
};

/**
* Moves the target index up one value.
*
Expand All @@ -159,6 +197,18 @@ export class DbxFormRepeatArrayTypeComponent<T = unknown> extends FieldArrayType
this.swapIndexes(index, index + 1);
}

duplicate(index: number) {
const array: unknown[] = this.model;
const targetValue = array[index];

if (!targetValue) {
return;
}

const targetIndex = this.addDuplicateToEnd ? array.length : index;
this.add(targetIndex, targetValue, { markAsDirty: true });
}

swapIndexes(currentIndex: number, targetIndex: number) {
const array: unknown[] = this.model;
const targetValue = array[currentIndex];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface RepeatArrayFieldConfig<T = unknown> extends DbxFormRepeatArrayC
}

export function repeatArrayField<T = unknown>(config: RepeatArrayFieldConfig<T>) {
const { key, label, description, repeatFieldGroup, maxLength, addText, removeText, labelForField, disableRearrange, allowAdd, allowRemove } = config;
const { key, label, description, repeatFieldGroup, maxLength, addText, removeText, duplicateText, labelForField, disableRearrange, allowAdd, allowRemove, allowDuplicate, addDuplicateToEnd } = config;

return formlyField({
key,
Expand All @@ -20,9 +20,12 @@ export function repeatArrayField<T = unknown>(config: RepeatArrayFieldConfig<T>)
labelForField,
addText,
removeText,
duplicateText,
disableRearrange,
allowAdd,
allowRemove
allowRemove,
allowDuplicate,
addDuplicateToEnd
}),
fieldArray: {
fieldGroup: asArray(repeatFieldGroup)
Expand Down
1 change: 1 addition & 0 deletions packages/dbx-web/src/lib/layout/text/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './form.description.component';
export * from './hint.component';
export * from './icon.spacer.component';
export * from './label.component';
Expand Down

0 comments on commit f4e027b

Please sign in to comment.