Skip to content

Commit

Permalink
Merge pull request #1745 from GuidoZam/DynamicForm-custom-icon
Browse files Browse the repository at this point in the history
Added customIcons property on DynamicForm.
  • Loading branch information
AJIXuMuK committed Feb 13, 2024
2 parents ff377a6 + c2c58d0 commit 83eed58
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 28 deletions.
1 change: 1 addition & 0 deletions docs/documentation/docs/controls/DynamicForm.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ The `DynamicForm` can be configured with the following properties:
| fieldOverrides | {[columnInternalName: string] : {(fieldProperties: IDynamicFieldProps): React.ReactElement\<IDynamicFieldProps\>}} | no | Key value pair for fields you want to override. Key is the internal field name, value is the function to be called for the custom element to render. |
| respectEtag | boolean | no | Specifies if the form should respect the ETag of the item. Default - `true` |
| validationErrorDialogProps | IValidationErrorDialogProps | no | Specifies validation error dialog properties |
| customIcons | { [ columnInternalName: string ]: string } | no | Specifies custom icons for the form. The key of this dictionary is the column internal name, the value is the Fluent UI icon name. |

## Validation Error Dialog Properties `IValidationErrorDialogProps`
| Property | Type | Required | Description |
Expand Down
7 changes: 5 additions & 2 deletions src/controls/dynamicForm/DynamicForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,7 @@ export class DynamicForm extends React.Component<
listItemId,
disabledFields,
respectETag,
customIcons,
onListItemLoaded,
} = this.props;
let contentTypeId = this.props.contentTypeId;
Expand Down Expand Up @@ -986,7 +987,8 @@ export class DynamicForm extends React.Component<
numberFields,
listId,
listItemId,
disabledFields
disabledFields,
customIcons
);

// Get installed languages for Currency fields
Expand Down Expand Up @@ -1028,7 +1030,7 @@ export class DynamicForm extends React.Component<
* @returns
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private async buildFieldCollection(listInfo: IRenderListDataAsStreamClientFormResult, contentTypeName: string, item: any, numberFields: ISPField[], listId: string, listItemId: number, disabledFields: string[]): Promise<IDynamicFieldProps[]> {
private async buildFieldCollection(listInfo: IRenderListDataAsStreamClientFormResult, contentTypeName: string, item: any, numberFields: ISPField[], listId: string, listItemId: number, disabledFields: string[], customIcons: {[key: string]: string}): Promise<IDynamicFieldProps[]> {
const tempFields: IDynamicFieldProps[] = [];
let order: number = 0;
const hiddenFields = this.props.hiddenFields !== undefined ? this.props.hiddenFields : [];
Expand Down Expand Up @@ -1285,6 +1287,7 @@ export class DynamicForm extends React.Component<
minimumValue: minValue,
maximumValue: maxValue,
showAsPercentage: showAsPercentage,
customIcon: customIcons ? customIcons[field.InternalName] : undefined
});

// This may not be necessary now using RenderListDataAsStream
Expand Down
14 changes: 13 additions & 1 deletion src/controls/dynamicForm/IDynamicFormProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,13 @@ export interface IDynamicFormProps {
/**
* Key value pair for fields you want to override. Key is the internal field name, value is the function to be called for the custom element to render
*/
fieldOverrides?: {[columnInternalName: string] : {(fieldProperties: IDynamicFieldProps): React.ReactElement<IDynamicFieldProps>}};
fieldOverrides?: {
[columnInternalName: string]: {
(
fieldProperties: IDynamicFieldProps
): React.ReactElement<IDynamicFieldProps>;
};
};

/**
* Specifies if onSubmitted event should pass PnPJS list item (IItem) as a second parameter. Default - true
Expand Down Expand Up @@ -110,4 +116,10 @@ export interface IDynamicFormProps {
* Only used when enableFileSelection is true
*/
supportedFileExtensions?: string[];

/**
* Specify a set of custom icons to be used.
* The key is the field internal name and the value is the Fluent UI icon name.
*/
customIcons?: { [columnInternalName: string]: string };
}
37 changes: 19 additions & 18 deletions src/controls/dynamicForm/dynamicField/DynamicField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi
description,
maximumValue,
minimumValue,
customIcon,
orderBy
} = this.props;

Expand Down Expand Up @@ -114,7 +115,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi
case 'Text':
return <div>
<div className={styles.titleContainer}>
<Icon className={styles.fieldIcon} iconName={"TextField"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "TextField"} />
{labelEl}
</div>
<TextField
Expand All @@ -135,7 +136,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi
const noteValue = valueToDisplay !== undefined ? valueToDisplay : defaultValue;
return <div className={styles.richText}>
<div className={styles.titleContainer}>
<Icon className={styles.fieldIcon} iconName={"AlignLeft"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "AlignLeft"} />
{labelEl}
</div>
<RichText
Expand All @@ -151,7 +152,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi
else {
return <div>
<div className={styles.titleContainer}>
<Icon className={styles.fieldIcon} iconName={"AlignLeft"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "AlignLeft"} />
{labelEl}
</div>
<TextField
Expand All @@ -172,7 +173,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi
case 'Choice':
return <div className={styles.fieldContainer}>
<div className={`${styles.labelContainer} ${styles.titleContainer}`}>
<Icon className={styles.fieldIcon} iconName={"CheckMark"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "CheckMark"} />
{labelEl}
</div>
<Dropdown
Expand All @@ -188,7 +189,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi
case 'MultiChoice':
return <div className={styles.fieldContainer}>
<div className={`${styles.labelContainer} ${styles.titleContainer}`}>
<Icon className={styles.fieldIcon} iconName={"MultiSelect"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "MultiSelect"} />
{labelEl}
</div>
<Dropdown
Expand All @@ -205,7 +206,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi
case 'Location':
return <div className={styles.fieldContainer}>
<div className={`${styles.labelContainer} ${styles.titleContainer}`}>
<Icon className={styles.fieldIcon} iconName={"POI"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "POI"} />
{labelEl}
</div>
<LocationPicker
Expand All @@ -224,7 +225,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi
const lookupValue = valueToDisplay !== undefined ? valueToDisplay : defaultValue;
return <div>
<div className={styles.titleContainer}>
<Icon className={styles.fieldIcon} iconName={"Switch"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "Switch"} />
{labelEl}
</div>
<ListItemPicker
Expand All @@ -249,7 +250,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi
const lookupMultiValue = valueToDisplay !== undefined ? valueToDisplay : defaultValue;
return <div>
<div className={styles.titleContainer}>
<Icon className={styles.fieldIcon} iconName={"Switch"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "Switch"} />
{labelEl}
</div>
<ListItemPicker
Expand All @@ -273,7 +274,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi

return <div>
<div className={styles.titleContainer}>
<Icon className={styles.fieldIcon} iconName={"NumberField"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "NumberField"} />
{labelEl}
</div>
<TextField
Expand All @@ -296,7 +297,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi

return <div>
<div className={styles.titleContainer}>
<Icon className={styles.fieldIcon} iconName={"AllCurrency"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "AllCurrency"} />
{labelEl}
</div>
<TextField
Expand All @@ -317,7 +318,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi
case 'DateTime':
return <div className={styles.fieldContainer}>
<div className={styles.titleContainer}>
<Icon className={styles.fieldIcon} iconName={"Calendar"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "Calendar"} />
{labelEl}
</div>
{
Expand Down Expand Up @@ -350,7 +351,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi
case 'Boolean':
return <div>
<div className={styles.titleContainer}>
<Icon className={styles.fieldIcon} iconName={"CheckboxComposite"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "CheckboxComposite"} />
{labelEl}
</div>
<Toggle
Expand All @@ -370,7 +371,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi
const userValue = Boolean(changedValue) ? changedValue.map(cv => cv.secondaryText) : (value ? value : defaultValue);
return <div>
<div className={styles.titleContainer}>
<Icon className={styles.fieldIcon} iconName={"Contact"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "Contact"} />
{labelEl}
</div>
<PeoplePicker
Expand All @@ -394,7 +395,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi
case 'UserMulti':
return <div>
<div className={styles.titleContainer}>
<Icon className={styles.fieldIcon} iconName={"Contact"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "Contact"} />
{labelEl}
</div>
<PeoplePicker
Expand All @@ -417,7 +418,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi
case 'URL':
return <div>
<div className={styles.titleContainer}>
<Icon className={styles.fieldIcon} iconName={"Link"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "Link"} />
{labelEl}
</div>
<Stack
Expand Down Expand Up @@ -446,7 +447,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi
case 'Thumbnail':
return <div>
<div className={styles.titleContainer}>
<Icon className={styles.fieldIcon} iconName={"photo2"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "photo2"} />
{labelEl}
</div>
<Stack
Expand Down Expand Up @@ -493,7 +494,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi
case 'TaxonomyFieldTypeMulti':
return <div className={styles.fieldContainer}>
<div className={styles.titleContainer}>
<Icon className={styles.fieldIcon} iconName={"BulletedTreeList"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "BulletedTreeList"} />
{labelEl}
</div>
<div className={styles.pickersContainer}>
Expand All @@ -518,7 +519,7 @@ export class DynamicField extends React.Component<IDynamicFieldProps, IDynamicFi
case 'TaxonomyFieldType':
return <div className={styles.fieldContainer}>
<div className={styles.titleContainer}>
<Icon className={styles.fieldIcon} iconName={"BulletedTreeList"} />
<Icon className={styles.fieldIcon} iconName={customIcon ?? "BulletedTreeList"} />
{labelEl}
</div>
<div className={styles.pickersContainer}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,6 @@ export interface IDynamicFieldProps {
maximumValue?: number;
minimumValue?: number;
showAsPercentage?: boolean;
customIcon?: string;
orderBy?: string;
}
18 changes: 11 additions & 7 deletions src/webparts/controlsTest/components/ControlsTest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,9 @@ export default class ControlsTest extends React.Component<IControlsTestProps, IC
dynamicFormListItemId = Number(this.props.dynamicFormListItemId);
}

const dynamicFormCustomTitleIcon: {[key: string]: string} = {};
dynamicFormCustomTitleIcon["Title"] = "FavoriteStar";

// Size options for the icon size dropdown
const sizeOptions: IDropdownOption[] = [
{
Expand Down Expand Up @@ -962,19 +965,20 @@ export default class ControlsTest extends React.Component<IControlsTestProps, IC
</div>
<div id="DynamicFormDiv" className={styles.container} hidden={!controlVisibility.DynamicForm}>
<div className="ms-font-m">
<DynamicForm
key={this.props.dynamicFormListId}
context={this.props.context}
listId={this.props.dynamicFormListId}
listItemId={dynamicFormListItemId}
<DynamicForm
key={this.props.dynamicFormListId}
context={this.props.context}
listId={this.props.dynamicFormListId}
listItemId={dynamicFormListItemId}
validationErrorDialogProps={this.props.dynamicFormErrorDialogEnabled ? { showDialogOnValidationError: true } : undefined}
returnListItemInstanceOnSubmit={true}
onCancelled={() => { console.log('Cancelled'); }}
onCancelled={() => { console.log('Cancelled'); }}
onSubmitted={async (data, item) => { let itemdata = await item.get(); console.log('Saved item', itemdata)}}
useClientSideValidation={this.props.dynamicFormClientSideValidationEnabled}
useFieldValidation={this.props.dynamicFormFieldValidationEnabled}
useCustomFormatting={this.props.dynamicFormCustomFormattingEnabled}
enableFileSelection={this.props.dynamicFormFileSelectionEnabled}
customIcons={dynamicFormCustomTitleIcon}
/>
</div>
</div>
Expand Down Expand Up @@ -2591,5 +2595,5 @@ export default class ControlsTest extends React.Component<IControlsTestProps, IC

// private _onFolderSelect = (folder: IFolder): void => {
// console.log('selected folder', folder);
//
//
}

0 comments on commit 83eed58

Please sign in to comment.