Overview
This blog will help us setup Material UI in SPFx and we will use the Stepper component from Material UI.
Introduction
With the introduction of SPFx, form creation in SharePoint has become easy. When creating huge forms it's great when we are able to divide the form into multiple sections. And to display this divided section it's even better to have a great UI experience. There are multiple options available, and a few are listed below:
For demo purposes we will use Material UI Stepper, but we can use any of the above as per our UI needs.
Create SPFx Project
The complete project can be downloaded from the below location.
To try in your environment use the below steps.
Step 1
Create one folder named materialUIStepper using the command below.
Navigate to the folder using the below command.
Run yeoman SharePoint Framework generator to create the project using the below command.
Step 2
Provide the values for the project as prompted by the yeoman generator. Below are the values which I provided for the example solution.
- What is your solution name? (material-ui-stepper)
- Which baseline packages do you want to target for your component(s)? SharePoint Online only (latest)
- Where do you want to place the files? (Use arrow keys) Use the current folder
- Do you want to allow the tenant admin the choice of being able to deploy the solution to all sites immediately without running any feature deployment or adding apps in sites? (y/N) N
- Will the components in the solution require permissions to access web APIs that are unique and not shared with other components in the tenant? (y/N) N
- Which type of client-side component to create? (Use arrow keys) WebPart
- What is your Web part name? materialuiStepper
- What is your Web part description? (materialuiStepper description)
- Which framework would you like to use? React
Step 3
Install Material UI with the below command we can even use Yarn to install Material UI.
- npm install @material-ui/core
Step 4
Open the src/webparts/materialuiStepper/components/MaterialuiStepper.tsx and make the following changes.
Import Statement
- import Stepper from '@material-ui/core/Stepper';
- import Step from '@material-ui/core/Step';
- import StepLabel from '@material-ui/core/StepLabel';
- import Typography from '@material-ui/core/Typography';
- import Button from '@material-ui/core/Button';
Add in State variable
- export interface IMaterialuiStepperState {
- activeStep: number;
- skipped: any;
- }
Update the state value in constructor
- public constructor(props: IMaterialuiStepperProps, state: IMaterialuiStepperState) {
- super(props);
- this.state = {
- activeStep: 0,
- skipped: new Set()
- };
- }
Create Steps Text
- private steps = ['Select campaign settings', 'Create an ad group', 'Create an ad'];
Content inside each step
We can use any other React component which we can create for each step and import that component and return for each step.
- private getStepContent = (step) => {
- switch (step) {
- case 0:
- return 'Select campaign settings...';
- case 1:
- return 'What is an ad group anyways?';
- case 2:
- return 'This is the bit I really care about!';
- default:
- return 'Unknown step';
- }
- }
HTML for steps (add inside render method)
- <Stepper activeStep={this.state.activeStep}>
- {this.steps.map((label, index) => {
- const props = {};
- const labelProps = {};
- if (this.isStepOptional(index)) {
- labelProps["optional"] = <Typography variant="caption">Optional</Typography>;
- }
- if (this.isStepSkipped(index)) {
- props["completed"] = false;
- }
- return (
- <Step key={label} {...props}>
- <StepLabel {...labelProps}>{label}</StepLabel>
- </Step>
- );
- })}
- </Stepper>
- <div>
- {this.state.activeStep === this.steps.length ? (
- <div>
- <Typography>
- All steps completed - you're finished
- </Typography>
- <Button onClick={this.handleReset}>
- Reset
- </Button>
- </div>
- ) : (
- <div>
- <Typography>{this.getStepContent(this.state.activeStep)}</Typography>
- <div>
- <Button disabled={this.state.activeStep===0} onClick={this.handleBack}>
- Back
- </Button>
- {this.isStepOptional(this.state.activeStep) && (
- <Button variant="contained" style={{ marginRight: 10 }} color="primary" onClick={this.handleSkip}>
- Skip
- </Button>
- )}
- <Button variant="contained" color="primary" onClick={this.handleNext}>
- {this.state.activeStep === this.steps.length - 1 ? 'Finish' : 'Next'}
- </Button>
- </div>
- </div>
- )}
- </div>
Add all helping methods for button click
- private isStepOptional = (step) => {
- return step === 1;
- }
- private isStepSkipped = (step) => {
- return this.state.skipped.has(step);
- }
- private handleNext = () => {
- const { activeStep } = this.state;
- let { skipped } = this.state;
- if (this.isStepSkipped(activeStep)) {
- skipped = new Set(skipped.values());
- skipped.delete(activeStep);
- }
- this.setState({
- activeStep: activeStep + 1,
- skipped,
- });
- }
- private handleBack = () => {
- this.setState(state => ({
- activeStep: state.activeStep - 1,
- }));
- }
- private handleSkip = () => {
- const { activeStep } = this.state;
- if (!this.isStepOptional(activeStep)) {
-
-
- throw new Error("You can't skip a step that isn't optional.");
- }
- this.setState(state => {
- const skipped = new Set(state.skipped.values());
- skipped.add(activeStep);
- return {
- activeStep: state.activeStep + 1,
- skipped,
- };
- });
- }
- private handleReset = () => {
- this.setState({
- activeStep: 0,
- });
- }
Outcome