Responsive Submit Form In SPFx
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.
After submitting data you will get an alert message.