Responsive Submit Form In SPFx

Vijaythapak
4 min readMar 21, 2023

--

ISubmitFormProps.ts File

import { WebPartContext } from "@microsoft/sp-webpart-base";

export interface ISubmitFormProps {
description: string;
context:WebPartContext;
siteUrl:string;
}

Now Go to SubmitFormWebpart.ts File and Update the following code.

import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import {
IPropertyPaneConfiguration,
PropertyPaneTextField
} from '@microsoft/sp-property-pane';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import { IReadonlyTheme } from '@microsoft/sp-component-base';

import * as strings from 'SubmitFormWebPartStrings';
import SubmitForm from './components/SubmitForm';
import { ISubmitFormProps } from './components/ISubmitFormProps';

export interface ISubmitFormWebPartProps {
description: string;
}

export default class SubmitFormWebPart extends BaseClientSideWebPart<ISubmitFormWebPartProps> {

// private _isDarkTheme: boolean = false;
// private _environmentMessage: string = '';

public render(): void {
const element: React.ReactElement<ISubmitFormProps> = React.createElement(
SubmitForm,
{
description: this.properties.description,
context:this.context,
siteUrl:this.context.pageContext.web.absoluteUrl
}
);

ReactDom.render(element, this.domElement);
}

protected onInit(): Promise<void> {
return this._getEnvironmentMessage().then(message => {
// this._environmentMessage = message;
// return super onInit()
});
}



private _getEnvironmentMessage(): Promise<string> {
if (!!this.context.sdks.microsoftTeams) { // running in Teams, office.com or Outlook
return this.context.sdks.microsoftTeams.teamsJs.app.getContext()
.then(context => {
let environmentMessage: string = '';
switch (context.app.host.name) {
case 'Office': // running in Office
environmentMessage = this.context.isServedFromLocalhost ? strings.AppLocalEnvironmentOffice : strings.AppOfficeEnvironment;
break;
case 'Outlook': // running in Outlook
environmentMessage = this.context.isServedFromLocalhost ? strings.AppLocalEnvironmentOutlook : strings.AppOutlookEnvironment;
break;
case 'Teams': // running in Teams
environmentMessage = this.context.isServedFromLocalhost ? strings.AppLocalEnvironmentTeams : strings.AppTeamsTabEnvironment;
break;
default:
throw new Error('Unknown host');
}

return environmentMessage;
});
}

return Promise.resolve(this.context.isServedFromLocalhost ? strings.AppLocalEnvironmentSharePoint : strings.AppSharePointEnvironment);
}

protected onThemeChanged(currentTheme: IReadonlyTheme | undefined): void {
if (!currentTheme) {
return;
}

// this._isDarkTheme = !!currentTheme.isInverted;
const {
semanticColors
} = currentTheme;

if (semanticColors) {
this.domElement.style.setProperty('--bodyText', semanticColors.bodyText || null);
this.domElement.style.setProperty('--link', semanticColors.link || null);
this.domElement.style.setProperty('--linkHovered', semanticColors.linkHovered || null);
}

}

protected onDispose(): void {
ReactDom.unmountComponentAtNode(this.domElement);
}

protected get dataVersion(): Version {
return Version.parse('1.0');
}

protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
header: {
description: strings.PropertyPaneDescription
},
groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneTextField('description', {
label: strings.DescriptionFieldLabel
})
]
}
]
}
]
};
}
}

Now Update SubmitForm.module.scss File

@import '~@fluentui/react/dist/sass/References.scss';

.submitForm {
overflow: hidden;
padding: 1em;
color: "[theme:bodyText, default: #323130]";
color: var(--bodyText);
&.teams {
font-family: $ms-font-family-fallbacks;
}
}
.form {
display: flex;
flex-direction: column;
gap: 16px;
max-width: 500px;
margin: 0 auto;
padding: 16px;
border: 1px solid #ccc;
border-radius: 4px;
// background-color: rgb(233, 192, 199);

div {
display: flex;
flex-direction: column;
gap: 8px;
}

.ms-Label {
font-weight: 600;
font-size: 16px;
color: hsl(0, 0%, 20%);
margin-bottom: 4px;
color:rgb(19, 207, 207)
}

.ms-TextField {
width: 100%;
max-width: 400px;
padding: 8px;
font-size: 16px;
color: #333;
border: 1px solid #ccc;
border-radius: 4px;

&:focus {
border-color: #0078d4;
outline: none;
box-shadow: 0 0 0 1px #0078d4;
}
}

.ms-Button {
margin-right: 16px;
}
}

Now come to the Main File SubmitForm.tsx and Update this file to

import * as React from 'react';
import styles from './SubmitForm.module.scss';
import { ISubmitFormProps } from './ISubmitFormProps';
import { DefaultButton, Dialog, DialogFooter, DialogType, Label, PrimaryButton, TextField } from 'office-ui-fabric-react';
import { Web } from "@pnp/sp/presets/all";
// import { escape } from '@microsoft/sp-lodash-subset';
import "@pnp/sp/lists";
import "@pnp/sp/items";
export interface ISubmitFormStates{
IStateItems:any;
ProductName:any;
ProductPrice:any;
Company:any;
showDialog: boolean;
}
export default class SubmitForm extends React.Component<ISubmitFormProps, ISubmitFormStates> {
constructor(props:ISubmitFormProps,state:ISubmitFormStates){
super(props);
this.state={
IStateItems:[],
ProductName:"",
ProductPrice:"",
Company:"",
showDialog: false,
}
}
public async componentDidMount() {
await this.FetchData();
}
public async FetchData(){
let web=Web(this.props.siteUrl);
const items:any[]= await web.lists.getByTitle("SubmitForm").items();
console.log("28",items);
this.setState({IStateItems:items});
}
// public onchange(value: any, stateValue: string): void {
// const state: Pick<ISubmitFormStates, keyof ISubmitFormStates> = {
// ...this.state,
// [stateValue]: value,
// };
// this.setState(state);
// }
public async CreateData(){
this.setState({showDialog: true});
}
public async onSaveChanges(){
// if (!this.props || !this.props.siteUrl) return;
let web=Web(this.props.siteUrl);
await web.lists.getByTitle("SubmitForm").items.add({
Title:this.state.ProductName,
Product_x0020_Price:this.state.ProductPrice,
Company:this.state.Company
}).then(i=>{
console.log(i);
});
alert("create successfully");
this.setState({ProductName:"",ProductPrice:"",Company:"",showDialog: false});
// this.FetchData();
}
public onCancelChanges() {
this.setState({showDialog: false});
}
public render(): React.ReactElement<ISubmitFormProps> {

return (
<div>
<form action="" className={styles.form} >
<div>
<Label className={styles['ms-Label']}>
Product Name
</Label>
<TextField value={this.state.ProductName} className={styles['ms-TextField']} onChange={(ev,newPlan)=>this.setState({ProductName:newPlan})}/>
</div>
<div>
<Label className={styles['ms-Label']}>
Product Price
</Label>
<TextField value={this.state.ProductPrice} className={styles['ms-TextField']} onChange={(ev,newPlan)=>this.setState({ProductPrice:newPlan})}/>
</div>
<div>
<Label className={styles['ms-Label']}>
Company
</Label>
<TextField value={this.state.Company} className={styles['ms-TextField']} onChange={(ev,newPlan)=>this.setState({Company:newPlan})}/>


</div>

<div>
{/* <PrimaryButton text='Save' onClick={()=>this.CreateData()}></PrimaryButton> */}
<PrimaryButton text='Submit Data' onClick={()=>this.CreateData()} className={styles['ms-Button']}></PrimaryButton>
{/* <DefaultButton text='Cancel' onClick={()=>this.setState({showDialog:true})}></DefaultButton> */}
</div>
<Dialog
hidden={!this.state.showDialog}
onDismiss={()=>this.onCancelChanges()}
dialogContentProps={{
type: DialogType.normal,
title: 'Do you want to save changes?',
subText: 'Your changes will be saved permanently.'
}}
modalProps={{
isBlocking: false,
}}
>
<DialogFooter>
<PrimaryButton onClick={()=>this.onSaveChanges()} text="Save" className={styles['ms-Button']} />
<DefaultButton onClick={()=>this.onCancelChanges()} text="Cancel" className={styles['ms-Button']}/>
</DialogFooter>
</Dialog>
</form>
</div>


);
}
}

Now run these commands in your terminal

gulp build
gulp serve

Your output would be like this.

This is the first Image when you will click on submit data button you will get a dialog like this
If you don’t want to save data you can simply click on cancel else you can click on the save button

After submitting data you will get an alert message.

--

--

Vijaythapak

I am wirter by passion. software Engineer by profession