PnP React Controls Part 16 – FieldCollectionData

Introduction

Hi everyone, this is part 16 of PnP React Controls Series. This post will explain the usage of the PnP FieldCollectionData control. We will see how we can leverage this control on our SPFx projects and make use of the feature provided by this control. Thanks to the community.

About the Control

This control acts as a on-demand list with limited set of features. If you have a functionality that would require different inputs of type from the user but its not required forever then this control would fit the best. There are some field controls which comes in default with this control and there is an option to render the custom control too. The data remains in the page as long as it is not refreshed. You can also store the data from this collection to the list or vice versa based on the business logic.

The fields are displayed in a very friendly way to the user in a panel. There is a search which we can configure so that the values can be searched based on the configured fields. Paging is also supported. There are lot of properties that we can use it to customize the control.

Focus on the Code

You can refer Part 1 post on the creation of the SPFx project and installing all the dependencies. In addition to the dependencies mentioned in that post you have to install @pnp/sp – v3.5.1. You should also do some changes to the project files to make the pnpjs version 3 to work on SPFx 1.14.0. Please follow this link to do the changes.

Created a webpart named fieldCollectionDataDemo. Below is the FieldCollectionDataDemo.tsx file.

import * as React from 'react';
import { FC, useState, useEffect } from 'react';
import styles from './FieldCollectionDataDemo.module.scss';
import { IFieldCollectionDataDemoProps } from './IFieldCollectionDataDemoProps';
import { FieldCollectionData, CustomCollectionFieldType } from '@pnp/spfx-controls-react/lib/FieldCollectionData';
import { Toggle } from '@fluentui/react/lib/Toggle';

const FieldCollectionDataDemo: FC<IFieldCollectionDataDemoProps> = (props) => {
    const {
        description,
        isDarkTheme,
        environmentMessage,
        hasTeamsContext,
        userDisplayName
    } = props;
    const [fieldValues, setFieldValues] = useState<any[]>(undefined);

    const _onFieldValuesChanged = (values: any[]) => {
        setFieldValues(values);
    };

    return (
        <section className={`${styles.fieldCollectionDataDemo} ${hasTeamsContext ? styles.teams : ''}`}>
            <div className={styles.welcome}>
                <img alt="" src={isDarkTheme ? require('../assets/welcome-dark.png') : require('../assets/welcome-light.png')} className={styles.welcomeImage} />
            </div>
            <div>
                <h3>PnP Field Collection Demo</h3>
                <div>
                    <FieldCollectionData
                        key={"FieldCollectionData"}
                        label={"Fields Collection"}
                        manageBtnLabel={"Manage"}
                        onChanged={_onFieldValuesChanged}
                        panelHeader={"Manage values"}

                        executeFiltering={(searchFilter: string, item: any) => {
                            return item["Field2"] === +searchFilter;
                        }}
                        itemsPerPage={3}
                        fields={[
                            { id: "Field1", title: "String field", type: CustomCollectionFieldType.string, required: true },
                            { id: "Field2", title: "Number field", type: CustomCollectionFieldType.number },
                            { id: "Field3", title: "URL field", type: CustomCollectionFieldType.url },
                            { id: "Field4", title: "Boolean field", type: CustomCollectionFieldType.boolean },
                            {
                                id: "Field5", title: "Dropdown Field", type: CustomCollectionFieldType.dropdown, options: [
                                    { key: 'Option1', text: 'Option 1' },
                                    { key: 'Option2', text: 'Option 2' },
                                    { key: 'Option3', text: 'Option 3' }]
                            },
                            { id: "Field6", title: "FabricIcon field", type: CustomCollectionFieldType.fabricIcon },
                            {
                                id: "Field7", title: "Custom Field", type: CustomCollectionFieldType.custom,
                                onCustomRender: (field, value, onUpdate, item, rowUniqueId, onCustomFieldValidation) => {
                                    console.log(field, value, item, rowUniqueId);
                                    return (
                                        <Toggle
                                            key={field.id}
                                            onText="On"
                                            offText="Off"
                                            checked={value}
                                            onChange={(ev: React.MouseEvent<HTMLElement>, checked?: boolean) => onUpdate(field.id, checked)}
                                        />
                                    );
                                },
                            }
                        ]}
                        value={fieldValues}
                    />
                    {fieldValues && fieldValues.length > 0 &&
                        <div>
                            <p>Selected Items</p>
                            <div>
                                <ul>
                                    {fieldValues.map((val) => {
                                        return (
                                            <li>
                                                <ul>
                                                    <li><b>String Field: </b>{val.Field1}</li>
                                                    <li><b>Number Field: </b>{val.Field2}</li>
                                                    <li><b>URL Field: </b>{val.Field3}</li>
                                                    <li><b>Boolean Field: </b>{val.Field4 ? 'true' : 'false'}</li>
                                                    <li><b>Dropdown Field: </b>{val.Field5}</li>
                                                    <li><b>FabricIcon Field: </b>{val.Field6}</li>
                                                    <li><b>Custom Toggle Field: </b>{val.Field7 ? 'true' : 'false'}</li>
                                                </ul>
                                            </li>
                                        )
                                    })}
                                </ul>
                            </div>
                        </div>
                    }
                </div>
            </div>
        </section>
    );
};

export default FieldCollectionDataDemo;

Below are the updates done to the file.

  • Changed the class component to the react hooks
  • Created a state variable to hold the values of different types. The values are stored as an array of items.
  • Following are some of the properties of the control that allows us to customize based on our requirement
    • onChange – Method executed where the values are changed.
    • fields – list of fields to be used for the data collection. It should have the following properties
      • id
      • title
      • type
      • onCustomRender – If the type is custom then this property is mandatory.
    • value – Variable to assign the values once the users save and close the panel.

There are other properties like label, panelHeader, panelDescription etc which are optional but the above properties are minimally required for the control to work.

Reference URL

FieldCollectionData – @pnp/spfx-controls-react

Sample Implementation

Conclussion

I hope you had learned something about one of the pnp control. There are lot to come in future.

Please free to post your comments and let me know if you want me to post article on any particular feature or plugins that relates to SharePoint. Thanks for your support.

sudharsank/pnpcontrols-demo: Demo project on different PnP React Controls. (github.com)

Happy Coding…

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s