In this SPFx tutorial, we will discuss, how to upload a file to a SharePoint Online document library with metadata in a SharePoint framework webpart. I will demonstrate, how to upload a file to the SharePoint library and update the metadata related to the file using an SPFx client-side webpart with react.
Recently, we got a requirement, where we need to upload files to the SharePoint document library with metadata in an SPFx web part. For example, we have a library ‘USA Citizenship’ in SharePoint Online and we wanted to upload files with metadata to this library using SPFx. To do this, we have created a form in an spfx client-side webpart, and when a user will fill in the form and click on Submit button, the file will be uploaded to the SharePoint library with metadata.
Upload File to SharePoint Document Library With Metadata in SPF Client Side WebPart
Here we will see how to upload a file and update metadata in the SharePoint library in an spfx client-side webpart.
Before we start creating a solution using the spfx client webpart, need to create a SharePoint library. I have created a SharePoint library ‘USA Citizenship’ with the below columns.
- CurrentLegalName – Single line of text
- NameExactlyOnYourPRC – Single line of text
- DOB -Date and Time
- CountryOfBirth -Single line of text
- CountryOfNationality – Single line of text
- MaritalStatus -Choice
- Email id– Single line of text
- Contact – Number
- Gender– Choice
- Disability -Choice (enable multiple selections)
By the end of the tutorial, you will able to create a form in the spfx client-side webpart using the SharePoint Framework, through which we can upload the file and update the metadata.
If you are new to spfx, you can check how to set up an spfx development environment and create your first webpart using react.
Follow the below steps to create a solution using spfx.
Step 1: Open the command prompt, create, and navigate to the project folder by using the below command.
mkdir usaCitizenshipForm
cd usaCitizenshipForm
Step 2: Run the below code to create the spfx solution using the Yeoman SharePoint generator.
yo @microsoft/sharepoint
The yeoman will ask you a list of questions like the below, to create a spfx project:
- ? What is your solution name? usa-citizenship-form (provide the solution name for the project )
- ? Which type of client-side component to create? WebPart (here you can see four choices I.e. Webpart, Extension, Library, Adaptive Card Extension, and select Webpart)
- ? What is your Web part name? UsaCitizenshipForm(provide webpart name)
- ? Which template would you like to use? React(select React, from 3 options :Minimal, React, No Framework)
It will take some time, to download and install all the dependencies required for the solution. Once the SPFx solution is created successfully, you can see a success message below.
Step 3: Now install the libraries which we will use in our spfx solution.
Install the Pnpjs library to interact with SharePoint Online library, for this use the below command:
npm install @pnp/sp@1.3.8 @pnp/odata@1.3.8 @pnp/logging@1.3.8 @pnp/common@1.3.8
Install the bootstrap library for styling the form, for this use the below command:
npm install bootstrap
Step 4: Once the prerequisite is done, now we are ready to open the solution in the visual studio code editor, so for this use the below command:
code .
As my solution is opened in visual studio code, you can see the project structure.
Step 5: Now navigate to the .tsx file, located in the ‘src\webparts\usaCitizenshipForm\components\UsaCitizenshipForm.tsx’.
Here first we will import all the files and components required to create the solution.
import * as React from 'react';
import styles from './UsaCitizenshipForm.module.scss';
import { IUsaCitizenshipFormProps } from './IUsaCitizenshipFormProps';
// import "@pnp/polyfill-ie11";
import { sp } from '@pnp/sp';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.min.js';
Step 6: Then define the “UsaCitizenshipForm” class, an extension of React.Component class, which accepts two parameters of type “IUsaCitizenshipFormProps” and any state.
A constructor for the class establishes the form’s initial state with empty strings, an empty array, and a success message.
The class contains a number of class methods for handling file submission, form reset, disabilityImpairment field validation, and form validation.
export default class UsaCitizenshipForm extends React.Component<IUsaCitizenshipFormProps, any> {
constructor(props: any) {
super(props);
this.state = {
currentLegalName: '',
nameExactlyOnYourPRC: '',
dob: '',
countryOfBirth: '',
countryOfNationality: '',
maritalStatus: '',
disabilityImpairment: [],
emailid: '',
contact: +9169966666,
gender: '',
successMessage: ''
};
this.filesave = this.filesave.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleDisabilityImpairment = this.handleDisabilityImpairment.bind(this);
this.resetForm = this.resetForm.bind(this);
this.validateForm = this.validateForm.bind(this);
}
......
....
}
Step 7: Define the “validateForm” method, and verifies that all needed fields are filled out. If they are not, an alert message is displayed, and the method returns false.
private validateForm() {
const { currentLegalName, nameExactlyOnYourPRC, countryOfBirth, countryOfNationality } = this.state;
if (!currentLegalName || !nameExactlyOnYourPRC || !countryOfBirth || !countryOfNationality) {
alert('Please fill in all the required fields.');
return false;
}
return true;
}
Step 8: Define the “resetForm” method to clear the file input and set the state of the form’s fields to their initial empty values. It also brings back the success message that was saved prior to the form’s reset.
private resetForm() {
const successMessage = this.state.successMessage; // store the success message
this.setState({
currentLegalName: '',
nameExactlyOnYourPRC: '',
dob: '',
countryOfBirth: '',
countryOfNationality: '',
maritalStatus: '',
disabilityImpairment: [],
emailid: '',
contact: +9169966666,
gender: ''
});
const fileInput = document.getElementById('newfile') as HTMLInputElement;
if (fileInput) {
fileInput.value = '';
}
this.setState({ successMessage }); // set the success message back after resetting the form
}
Step 9: Define the “handleDisabilityImpairment” method handles the inputs from the checkboxes for the disabilityImpairment field. When a checkbox is selected, the disabilityImpairment array is expanded to include the value. When it is unchecked, the value is taken out of the array.
private handleDisabilityImpairment = ({ target }: React.ChangeEvent<HTMLInputElement>) => {
const { value, checked } = target;
const { disabilityImpairment } = this.state;
if (checked) {
// Add the selected disabilityImpairment to the array if it doesn't exist
if (!disabilityImpairment.includes(value)) {
this.setState((prevState: any) => ({
disabilityImpairment: [...prevState.disabilityImpairment, value]
}));
} console.log(disabilityImpairment);
} else {
// Remove the deselected disabilityImpairment from the array
this.setState((prevState: any) => ({
disabilityImpairment: prevState.disabilityImpairment.filter((c: any) => c !== value)
}));
} console.log(disabilityImpairment);
};
Step 10: Now, the form submission is going to be handled by the “filesave” method. In order to verify that all needed fields are filled in, it first invokes the “validateForm” method.
The file is then taken from the file input control, and the folder and file URLs are configured. If the file already exists, a notification is displayed and an attempt is made to obtain it through the server-relative URL. It uploads the file to the folder and adds the form data to the file’s metadata if the file doesn’t already exist.
private async filesave() {
if (!this.validateForm()) {
return;
}
const myfile = (document.querySelector("#newfile") as HTMLInputElement).files[0];
const folderUrl = "/sites/TsInfoTechDeveloper/USA%20Citizenship";
const fileUrl = `${folderUrl}/${myfile.name}`;
try {
// Try to get the file by its server-relative URL
await sp.web.getFileByServerRelativeUrl(fileUrl).get();
console.log(`File "${myfile.name}" already exists in the folder "${folderUrl}".`);
} catch (error) {
if (error.status === 404) {
if (myfile.size <= 10486760) {
sp.web.getFolderByServerRelativeUrl(folderUrl).files.add(myfile.name, myfile, true).then(f => {
console.log("File Uploaded");
f.file.getItem().then(item => {
item.update({
Title: "Metadata Updated",
CurrentLegalName: this.state.currentLegalName,
NameExactlyOnYourPRC: this.state.nameExactlyOnYourPRC,
DOB: this.state.dob,
CountryOfBirth: this.state.countryOfBirth,
CountryOfNationality: this.state.countryOfNationality,
MaritalStatus: this.state.maritalStatus,
Disabilty: { results: this.state.disabilityImpairment },
Emailid: this.state.emailid,
Contact: this.state.contact,
Gender: this.state.gender
}).then((myupdate: any) => {
console.log(myupdate);
console.log("Metadata Updated");
this.setState({ successMessage: 'Data saved successfully.' });
this.resetForm();
});
});
});
} else {
sp.web.getFolderByServerRelativeUrl(folderUrl)
.files.addChunked(myfile.name, myfile)
.then(({ file }) => file.getItem()).then((item: any) => {
console.log("File Uploaded");
return item.update({
Title: "Metadata Updated",
CurrentLegalName: this.state.currentLegalName,
NameExactlyOnYourPRC: this.state.nameExactlyOnYourPRC,
DOB: this.state.dob,
CountryOfBirth: this.state.countryOfBirth,
CountryOfNationality: this.state.countryOfNationality,
MaritalStatus: this.state.maritalStatus,
Disabilty: { results: this.state.disabilityImpairment },
Emailid: this.state.emailid,
Contact: this.state.contact,
Gender: this.state.gender
}).then((myupdate: any) => {
console.log(myupdate);
console.log("Metadata Updated");
this.setState({ successMessage: 'Data saved successfully successfully.' });
this.resetForm();
});
}).catch(console.log);
}
} else {
console.log(`Error while getting the file "${myfile.name}" at "${fileUrl}":`, error);
}
}
}
Step 11: Define the ‘handleChange‘ method, which is in charge of updating the state of the component as the user fills out the form.
private handleChange(event: any) {
const target = event.target;
const value = target.value;
const name = target.name;
this.setState({
[name]: value
});
}
Step 12: The render method exhibits the form, complete with all required input fields, labels, and placeholders. A success message is displayed when the user successfully submits the form.
public render(): React.ReactElement<IUsaCitizenshipFormProps> {
const { successMessage } = this.state;
return (
<section className={`${styles.usaCitizenshipForm}`}>
<div >
<h1 className='text-center fs-2 text-primary'>Citizenship Form</h1><br/>
{successMessage && <p className='fs-5 fw-semibold text-success'>{successMessage}</p>}
{/* For current legal name */}
<div className="form-group">
<label htmlFor="currentLegalName" className="fs-6">Current Legal Name*:</label>
<input type="text" id="currentLegalName" name="currentLegalName" value={this.state.currentLegalName} onChange={this.handleChange} className="form-control" placeholder="Current Legal Name" required />
</div>
{/*Name exactly on your PRC */}
<div className="form-group">
<label htmlFor="nameExactlyOnYourPRC" className="fs-6">Name exactly as it appears on your Permanent Resident Card (PRC):</label>
<input type="text" className="form-control" id="nameExactlyOnYourPRC" name="nameExactlyOnYourPRC" value={this.state.nameExactlyOnYourPRC} onChange={this.handleChange} placeholder="Enter name as it appears on your PRC" required />
</div>
{/* Date Of Birth */}
<div className="form-group">
<label htmlFor="dob" className="fs-6">Date of Birth:</label>
<input type="date" className="form-control" id="dob" name="dob" value={this.state.dob} onChange={this.handleChange} required />
</div>
{/* Marital Status */}
<div className="form-group">
<label htmlFor="maritalStatus" className="fs-6">Marital Status:</label>
<select className="form-control" id="maritalStatus" name="maritalStatus" value={this.state.maritalStatus} onChange={this.handleChange}>
<option value="">-- Select Marital Status --</option>
<option value="Single">Single</option>
<option value="Married">Married</option>
<option value="Divorced">Divorced</option>
<option value="Widowed">Widowed</option>
</select>
</div>
{/* Disability Imparent */}
<div className='form-group'>
<label className="form-check-label fs-6" htmlFor="flexCheckDefault">Disability Imparent:</label><br />
<div>
<input className="form-check-input" type="checkbox" name="I am deaf or hearing impaired and need a sign language interpreter who uses my language" value="I am deaf or hearing impaired and need a sign language interpreter who uses my language" onChange={this.handleDisabilityImpairment} checked={this.state.disabilityImpairment.includes("I am deaf or hearing impaired and need a sign language interpreter who uses my language")} />
<label className="form-check-label fs-6" htmlFor="flexCheckDefault">I am deaf or hearing impaired and need a sign language interpreter who uses my language</label><br />
</div>
<div>
<input className="form-check-input" type="checkbox" name="I use a wheelchair" value="I use a wheelchair" onChange={this.handleDisabilityImpairment} checked={this.state.disabilityImpairment.includes("I use a wheelchair")} />
<label className="form-check-label fs-6" htmlFor="flexCheckDefault"> I use a wheelchair</label><br />
</div>
<div>
<input className="form-check-input" type="checkbox" name="I am blind or sight impaired" value="I am blind or sight impaired" onChange={this.handleDisabilityImpairment} checked={this.state.disabilityImpairment.includes("I am blind or sight impaired")} />
<label className="form-check-label fs-6" htmlFor="flexCheckDefault">I am blind or sight impaired</label><br />
</div>
<div> <input className="form-check-input" type="checkbox" name="I will need another type of accommodation" value="I will need another type of accommodation" onChange={this.handleDisabilityImpairment} checked={this.state.disabilityImpairment.includes("I will need another type of accommodation")} />
<label className="form-check-label fs-6" htmlFor="flexCheckDefault">I will need another type of accommodation</label><br />
</div>
</div>
{/* Country of Nationality */}
<div className="form-group">
<label htmlFor="countryOfNationality" className="fs-6">Country Of Nationality*:</label>
<select className="form-control" id="countryOfNationality" name="countryOfNationality" value={this.state.countryOfNationality} onChange={this.handleChange} required>
<option value="">-- Select Country Of Nationality --</option>
<option value="">Select</option>
<option value="USA">USA</option>
<option value="UK">UK</option>
<option value="Australia">Australia</option>
<option value="UAE">UAE</option>
</select>
</div>
{/* Country of Birth */}
<div className="form-group">
<label htmlFor="countryOfBirth" className="fs-6">Country Of Birth*:</label>
<select className="form-control" id="countryOfBirth" name="countryOfBirth" value={this.state.countryOfBirth} onChange={this.handleChange} required>
<option value="">-- Select Country Of Birth* --</option>
<option value="">Select</option>
<option value="USA">USA</option>
<option value="UK">UK</option>
<option value="Australia">Australia</option>
<option value="UAE">UAE</option>
</select>
</div>
{/* Email Id */}
<div className="form-group">
<label htmlFor="emailid" className="fs-6">Email Id:</label> <br />
<input type="email" className="form-control" id="emailid" name="emailid" value={this.state.emailid} onChange={this.handleChange} />
</div>
{/* Contact */}
<div className="form-group">
<label htmlFor="contact" className="fs-6">Contact Number:</label> <br />
<input type="tel" className="form-control" id="contact" name="contact" value={this.state.contact} onChange={this.handleChange} pattern="[0-9]{3}-[0-9]{2}-[0-9]{3}" />
</div>
{/* Gender */}
<div className="form-group">
<label htmlFor="gender" className="fs-6">Gender:</label> <br />
<select className="form-control" id="gender" name="gender" value={this.state.gender} onChange={this.handleChange} required>
<option value="">-- Select gender --</option>
<option value="">Select</option>
<option value="Male">Male</option>
<option value="Female">Female</option>
<option value="Other">Other</option>
</select>
</div>
{/* Upload file */}
<div className="mb-3">
<label htmlFor="formFile" className="form-label fs-6">Upload Identity Proof:</label><br />
<input className="form-control" type="file" name="myFile" id="newfile"></input>
</div>
<div>
<button className="btn btn-primary" type='submit' onClick={this.filesave}>
Submit
</button>
</div>
</div>
</section>
);
}
Here is the full code for .tsx file.
import * as React from 'react';
import styles from './UsaCitizenshipForm.module.scss';
import { IUsaCitizenshipFormProps } from './IUsaCitizenshipFormProps';
// import "@pnp/polyfill-ie11";
import { sp } from '@pnp/sp';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.min.js';
export default class UsaCitizenshipForm extends React.Component<IUsaCitizenshipFormProps, any> {
constructor(props: any) {
super(props);
this.state = {
currentLegalName: '',
nameExactlyOnYourPRC: '',
dob: '',
countryOfBirth: '',
countryOfNationality: '',
maritalStatus: '',
disabilityImpairment: [],
emailid: '',
contact: +9169966666,
gender: '',
successMessage: ''
};
this.filesave = this.filesave.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleDisabilityImpairment = this.handleDisabilityImpairment.bind(this);
this.resetForm = this.resetForm.bind(this);
this.validateForm = this.validateForm.bind(this);
}
// handle validation for candidateName Field
private validateForm() {
const { currentLegalName, nameExactlyOnYourPRC, countryOfBirth, countryOfNationality } = this.state;
if (!currentLegalName || !nameExactlyOnYourPRC || !countryOfBirth || !countryOfNationality) {
alert('Please fill in all the required fields.');
return false;
}
return true;
}
// reset the field to initial state
private resetForm() {
const successMessage = this.state.successMessage; // store the success message
this.setState({
currentLegalName: '',
nameExactlyOnYourPRC: '',
dob: '',
countryOfBirth: '',
countryOfNationality: '',
maritalStatus: '',
disabilityImpairment: [],
emailid: '',
contact: +9169966666,
gender: ''
});
const fileInput = document.getElementById('newfile') as HTMLInputElement;
if (fileInput) {
fileInput.value = '';
}
this.setState({ successMessage }); // set the success message back after resetting the form
}
//handle disabilityImpairment field validation
private handleDisabilityImpairment = ({ target }: React.ChangeEvent<HTMLInputElement>) => {
const { value, checked } = target;
const { disabilityImpairment } = this.state;
if (checked) {
// Add the selected disabilityImpairment to the array if it doesn't exist
if (!disabilityImpairment.includes(value)) {
this.setState((prevState: any) => ({
disabilityImpairment: [...prevState.disabilityImpairment, value]
}));
} console.log(disabilityImpairment);
} else {
// Remove the deselected disabilityImpairment from the array
this.setState((prevState: any) => ({
disabilityImpairment: prevState.disabilityImpairment.filter((c: any) => c !== value)
}));
} console.log(disabilityImpairment);
};
//handle field submission
private async filesave() {
if (!this.validateForm()) {
return;
}
const myfile = (document.querySelector("#newfile") as HTMLInputElement).files[0];
const folderUrl = "/sites/TsInfoTechDeveloper/USA%20Citizenship";
const fileUrl = `${folderUrl}/${myfile.name}`;
try {
// Try to get the file by its server-relative URL
await sp.web.getFileByServerRelativeUrl(fileUrl).get();
console.log(`File "${myfile.name}" already exists in the folder "${folderUrl}".`);
} catch (error) {
if (error.status === 404) {
if (myfile.size <= 10486760) {
sp.web.getFolderByServerRelativeUrl(folderUrl).files.add(myfile.name, myfile, true).then(f => {
console.log("File Uploaded");
f.file.getItem().then(item => {
item.update({
Title: "Metadata Updated",
CurrentLegalName: this.state.currentLegalName,
NameExactlyOnYourPRC: this.state.nameExactlyOnYourPRC,
DOB: this.state.dob,
CountryOfBirth: this.state.countryOfBirth,
CountryOfNationality: this.state.countryOfNationality,
MaritalStatus: this.state.maritalStatus,
Disabilty: { results: this.state.disabilityImpairment },
Emailid: this.state.emailid,
Contact: this.state.contact,
Gender: this.state.gender
}).then((myupdate: any) => {
console.log(myupdate);
console.log("Metadata Updated");
this.setState({ successMessage: 'Data saved successfully.' });
this.resetForm();
});
});
});
} else {
sp.web.getFolderByServerRelativeUrl(folderUrl)
.files.addChunked(myfile.name, myfile)
.then(({ file }) => file.getItem()).then((item: any) => {
console.log("File Uploaded");
return item.update({
Title: "Metadata Updated",
CurrentLegalName: this.state.currentLegalName,
NameExactlyOnYourPRC: this.state.nameExactlyOnYourPRC,
DOB: this.state.dob,
CountryOfBirth: this.state.countryOfBirth,
CountryOfNationality: this.state.countryOfNationality,
MaritalStatus: this.state.maritalStatus,
Disabilty: { results: this.state.disabilityImpairment },
Emailid: this.state.emailid,
Contact: this.state.contact,
Gender: this.state.gender
}).then((myupdate: any) => {
console.log(myupdate);
console.log("Metadata Updated");
this.setState({ successMessage: 'Data saved successfully successfully.' });
this.resetForm();
});
}).catch(console.log);
}
} else {
console.log(`Error while getting the file "${myfile.name}" at "${fileUrl}":`, error);
}
}
}
private handleChange(event: any) {
const target = event.target;
const value = target.value;
const name = target.name;
this.setState({
[name]: value
});
}
public render(): React.ReactElement<IUsaCitizenshipFormProps> {
const { successMessage } = this.state;
return (
<section className={`${styles.usaCitizenshipForm}`}>
<div >
<h1 className='text-center fs-2 text-primary'>Citizenship Form</h1><br/>
{successMessage && <p className='fs-5 fw-semibold text-success'>{successMessage}</p>}
{/* For current legal name */}
<div className="form-group">
<label htmlFor="currentLegalName" className="fs-6">Current Legal Name*:</label>
<input type="text" id="currentLegalName" name="currentLegalName" value={this.state.currentLegalName} onChange={this.handleChange} className="form-control" placeholder="Current Legal Name" required />
</div>
{/*Name exactly on your PRC */}
<div className="form-group">
<label htmlFor="nameExactlyOnYourPRC" className="fs-6">Name exactly as it appears on your Permanent Resident Card (PRC):</label>
<input type="text" className="form-control" id="nameExactlyOnYourPRC" name="nameExactlyOnYourPRC" value={this.state.nameExactlyOnYourPRC} onChange={this.handleChange} placeholder="Enter name as it appears on your PRC" required />
</div>
{/* Date Of Birth */}
<div className="form-group">
<label htmlFor="dob" className="fs-6">Date of Birth:</label>
<input type="date" className="form-control" id="dob" name="dob" value={this.state.dob} onChange={this.handleChange} required />
</div>
{/* Marital Status */}
<div className="form-group">
<label htmlFor="maritalStatus" className="fs-6">Marital Status:</label>
<select className="form-control" id="maritalStatus" name="maritalStatus" value={this.state.maritalStatus} onChange={this.handleChange}>
<option value="">-- Select Marital Status --</option>
<option value="Single">Single</option>
<option value="Married">Married</option>
<option value="Divorced">Divorced</option>
<option value="Widowed">Widowed</option>
</select>
</div>
{/* Disability Imparent */}
<div className='form-group'>
<label className="form-check-label fs-6" htmlFor="flexCheckDefault">Disability Imparent:</label><br />
<div>
<input className="form-check-input" type="checkbox" name="I am deaf or hearing impaired and need a sign language interpreter who uses my language" value="I am deaf or hearing impaired and need a sign language interpreter who uses my language" onChange={this.handleDisabilityImpairment} checked={this.state.disabilityImpairment.includes("I am deaf or hearing impaired and need a sign language interpreter who uses my language")} />
<label className="form-check-label fs-6" htmlFor="flexCheckDefault">I am deaf or hearing impaired and need a sign language interpreter who uses my language</label><br />
</div>
<div>
<input className="form-check-input" type="checkbox" name="I use a wheelchair" value="I use a wheelchair" onChange={this.handleDisabilityImpairment} checked={this.state.disabilityImpairment.includes("I use a wheelchair")} />
<label className="form-check-label fs-6" htmlFor="flexCheckDefault"> I use a wheelchair</label><br />
</div>
<div>
<input className="form-check-input" type="checkbox" name="I am blind or sight impaired" value="I am blind or sight impaired" onChange={this.handleDisabilityImpairment} checked={this.state.disabilityImpairment.includes("I am blind or sight impaired")} />
<label className="form-check-label fs-6" htmlFor="flexCheckDefault">I am blind or sight impaired</label><br />
</div>
<div> <input className="form-check-input" type="checkbox" name="I will need another type of accommodation" value="I will need another type of accommodation" onChange={this.handleDisabilityImpairment} checked={this.state.disabilityImpairment.includes("I will need another type of accommodation")} />
<label className="form-check-label fs-6" htmlFor="flexCheckDefault">I will need another type of accommodation</label><br />
</div>
</div>
{/* Country of Nationality */}
<div className="form-group">
<label htmlFor="countryOfNationality" className="fs-6">Country Of Nationality*:</label>
<select className="form-control" id="countryOfNationality" name="countryOfNationality" value={this.state.countryOfNationality} onChange={this.handleChange} required>
<option value="">-- Select Country Of Nationality --</option>
<option value="">Select</option>
<option value="USA">USA</option>
<option value="UK">UK</option>
<option value="Australia">Australia</option>
<option value="UAE">UAE</option>
</select>
</div>
{/* Country of Birth */}
<div className="form-group">
<label htmlFor="countryOfBirth" className="fs-6">Country Of Birth*:</label>
<select className="form-control" id="countryOfBirth" name="countryOfBirth" value={this.state.countryOfBirth} onChange={this.handleChange} required>
<option value="">-- Select Country Of Birth* --</option>
<option value="">Select</option>
<option value="USA">USA</option>
<option value="UK">UK</option>
<option value="Australia">Australia</option>
<option value="UAE">UAE</option>
</select>
</div>
{/* Email Id */}
<div className="form-group">
<label htmlFor="emailid" className="fs-6">Email Id:</label> <br />
<input type="email" className="form-control" id="emailid" name="emailid" value={this.state.emailid} onChange={this.handleChange} />
</div>
{/* Contact */}
<div className="form-group">
<label htmlFor="contact" className="fs-6">Contact Number:</label> <br />
<input type="tel" className="form-control" id="contact" name="contact" value={this.state.contact} onChange={this.handleChange} pattern="[0-9]{3}-[0-9]{2}-[0-9]{3}" />
</div>
{/* Gender */}
<div className="form-group">
<label htmlFor="gender" className="fs-6">Gender:</label> <br />
<select className="form-control" id="gender" name="gender" value={this.state.gender} onChange={this.handleChange} required>
<option value="">-- Select gender --</option>
<option value="">Select</option>
<option value="Male">Male</option>
<option value="Female">Female</option>
<option value="Other">Other</option>
</select>
</div>
{/* Upload file */}
<div className="mb-3">
<label htmlFor="formFile" className="form-label fs-6">Upload Identity Proof:</label><br />
<input className="form-control" type="file" name="myFile" id="newfile"></input>
</div>
<div>
<button className="btn btn-primary" type='submit' onClick={this.filesave}>
Submit
</button>
</div>
</div>
</section>
);
}
}
Step 13: To configure the workbench, go to the serve.json file located in the ‘config\serve.json’. Here provide the SharePoint site in the initial properties, to run the solution on the local server.
Step 14: To compile the spfx solution, and run the solution in the local server, write the below command.
gulp serve
Now the user will redirect to the browser, click on the + icon and then select the webpart under the local section.
Now fill in the data in the form, upload a file, and then click on submit, you can the file is uploaded and the metadata gets updated.
This is how we can upload a file and insert the metadata in the SharePoint document library by using spfx.
Download the SPFx Solution
To download the solution click on this link, and then unzip the solution folder and run the below command. Make sure to create the document library and add the required metadata columns.
npm i
Conclusion
In this spfx tutorial, we saw, how to upload a file to a SharePoint document library in an SPFx client-side solution. Also, we saw, how to set up metadata for the file inside the SharePoint document library.
You may like the following SharePoint framework tutorials:
- How do I use Office UI fabric in SPFx?
- How to Configure Web Part Icon in SPFx
- Create SPFx Web Part with jQuery Accordion
- add custom controls in SPFx property pane
I am Bijay a Microsoft MVP (10 times – My MVP Profile) in SharePoint and have more than 17 years of expertise in SharePoint Online Office 365, SharePoint subscription edition, and SharePoint 2019/2016/2013. Currently working in my own venture TSInfo Technologies a SharePoint development, consulting, and training company. I also run the popular SharePoint website EnjoySharePoint.com