Automatically generating a table of contents (TOC) in a Word document using JavaScript within a React application streamlines document creation by eliminating manual updates and ensuring dynamic consistency. This approach is particularly valuable in scenarios where content length, structure, or headings frequently change, such as in report-generation tools, academic platforms, or documentation systems. By leveraging Spire.Doc for JavaScript's WebAssembly module and React’s reactive state management, developers can programmatically detect headings, organize hierarchical sections, and insert hyperlinked TOC entries directly into Word files. In this article, we will explore how to use Spire.Doc for JavaScript to insert tables of contents into Word documents with JavaScript in React applications.
- Insert a Default TOC into a Word Document Using JavaScript
- Insert a Custom TOC into a Word Document Using JavaScript
- Remove the Table of Contents from a Word Document
Install Spire.Doc for JavaScript
To get started with inserting tables of contents into Word documents in a React application, you can either download Spire.Doc for JavaScript from our website or install it via npm with the following command:
npm i spire.doc
After that, copy the "Spire.Doc.Base.js" and "Spire.Doc.Base.wasm" files into the public folder of your project. Additionally, include the required font files to ensure accurate and consistent text rendering.
For more details, refer to the documentation: How to Integrate Spire.Doc for JavaScript in a React Project
Insert a Default TOC into a Word Document Using JavaScript
Spire.Doc for JavaScript offers a WebAssembly module for processing Word documents in JavaScript environments. You can load a Word document from the virtual file system using the Document.LoadFromFile() method and insert a table of contents (TOC) via the Paragraph.AppendTOC() method, which auto-generates based on the document’s titles. Finally, update the TOC with the Document.UpdateTableOfContents() method.
The detailed steps are as follows:
- Load the Spire.Doc.Base.js file to initialize the WebAssembly module.
- Fetch the Word file to the virtual file system (VFS) using the wasmModule.FetchFileToVFS() method.
- Create an instance of the Document class in the VFS using the wasmModule.Document.Create() method.
- Load the Word document from the VFS using the Document.LoadFromFile() method.
- Add a new section to the document using the Document.AddSection() method, and add a paragraph using the Section.AddParagraph() method.
- Insert the section after the cover section using the Document.Sections.Insert() method.
- Insert a TOC into the paragraph using the Paragraph.AppendTOC() method.
- Update the TOC using the Document.UpdateTableOfContents() method.
- Save the document to the VFS using the Document.SaveToFile() method.
- Read the document from the VFS and download it.
- JavaScript
import React, { useState, useEffect } from 'react'; function App() { // State to store the loaded WASM module const [wasmModule, setWasmModule] = useState(null); // useEffect hook to load the WASM module when the component mounts useEffect(() => { const loadWasm = async () => { try { // Access the Module and spiredoc from the global window object const { Module, spiredoc } = window; // Set the wasmModule state when the runtime is initialized Module.onRuntimeInitialized = () => { setWasmModule(spiredoc); }; } catch (err) { // Log any errors that occur during module loading console.error('Failed to load the WASM module:', err); } }; // Create a script element to load the WASM JavaScript file const script = document.createElement('script'); script.src = `${process.env.PUBLIC_URL}/Spire.Doc.Base.js`; script.onload = loadWasm; // Append the script to the document body document.body.appendChild(script); // Cleanup function to remove the script when the component unmounts return () => { document.body.removeChild(script); }; }, []); // Function to insert a default table of contents into a Word document const InsertTOCWord = async () => { if (wasmModule) { // Specify the input and output file names const inputFileName = 'Sample.docx'; const outputFileName = 'DefaultTOC.docx'; // Fetch the font file and add it to the VFS await wasmModule.FetchFileToVFS('HarmonyOS_Sans_SC_Regular.ttf', '/Library/Fonts/', `${process.env.PUBLIC_URL}/`); // Fetch the input file and add it to the VFS await wasmModule.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/`); // Create an instance of the Document class const doc = wasmModule.Document.Create(); // Load the Word document doc.LoadFromFile({ fileName: inputFileName }); // Create a new section const section = doc.AddSection(); // Create a new paragraph const paragraph = section.AddParagraph(); // Add a table of contents to the paragraph paragraph.AppendTOC(1, 2); // Insert the section after the cover section doc.Sections.Insert(1, section); // Update the table of contents doc.UpdateTableOfContents(); // Save the document to the VFS doc.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.Docx2019}) // Read the document from the VFS and create a Blob to trigger the download const wordArray = await wasmModule.FS.readFile(outputFileName); const blob = new Blob([wordArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `${outputFileName}`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } }; return ( <div style={{ textAlign: 'center', height: '300px' }}> <h1>Insert Default Table of Contents Using JavaScript in React</h1> <button onClick={InsertTOCWord} disabled={!wasmModule}> Insert and Download </button> </div> ); } export default App;
Insert a Custom TOC into a Word Document Using JavaScript
Spire.Doc for JavaScript also enables users to create a custom table of contents. By creating an instance of the TableOfContent class, you can customize title and page number display using switches. For instance, the switch "{\o "1-3" \n 1-1}" configures the TOC to display titles from level 1 to 3 while omitting page numbers for level 1 titles. After creating the instance, insert it into the document and assign it as the TOC of the document using the Document.TOC property.
The detailed steps are as follows:
- Load the Spire.Doc.Base.js file to initialize the WebAssembly module.
- Fetch the Word file to the virtual file system (VFS) using the wasmModule.FetchFileToVFS() method.
- Create an instance of the Document class in the VFS using the wasmModule.Document.Create() method.
- Load the Word document from the VFS using the Document.LoadFromFile() method.
- Add a new section to the document using the Document.AddSection() method, and add a paragraph using the Section.AddParagraph() method.
- Insert the section after the cover section using the Document.Sections.Insert() method.
- Create an instance of the TableOfContent class in the VFS using the wasmModule.TableOfContent.Create() method and specify the switch.
- Insert the TOC into the new paragraph using the Paragraph.Items.Add() method.
- Append the field separator and field end marks to complete the TOC field using the Paragraph.AppendFieldMark() method.
- Set the new TOC as the document’s TOC through the Document.TOC property.
- Update the TOC using the Document.UpdateTableOfContents() method.
- Save the document to the VFS using the Document.SaveToFile() method.
- Read the document from the VFS and download it.
- JavaScript
import React, { useState, useEffect } from 'react'; function App() { // State to store the loaded WASM module const [wasmModule, setWasmModule] = useState(null); // useEffect hook to load the WASM module when the component mounts useEffect(() => { const loadWasm = async () => { try { // Access the Module and spiredoc from the global window object const { Module, spiredoc } = window; // Set the wasmModule state when the runtime is initialized Module.onRuntimeInitialized = () => { setWasmModule(spiredoc); }; } catch (err) { // Log any errors that occur during module loading console.error('Failed to load the WASM module:', err); } }; // Create a script element to load the WASM JavaScript file const script = document.createElement('script'); script.src = `${process.env.PUBLIC_URL}/Spire.Doc.Base.js`; script.onload = loadWasm; // Append the script to the document body document.body.appendChild(script); // Cleanup function to remove the script when the component unmounts return () => { document.body.removeChild(script); }; }, []); // Function to insert a custom table of contents into a Word document const InsertTOCWord = async () => { if (wasmModule) { // Specify the input and output file names const inputFileName = 'Sample.docx'; const outputFileName = 'CustomTOC.docx'; // Fetch the font file and add it to the VFS await wasmModule.FetchFileToVFS('HarmonyOS_Sans_SC_Regular.ttf', '/Library/Fonts/', `${process.env.PUBLIC_URL}/`); // Fetch the input file and add it to the VFS await wasmModule.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/`); // Create an instance of the Document class const doc = wasmModule.Document.Create(); // Load the Word document doc.LoadFromFile({ fileName: inputFileName }); // Add a new section and paragraph const section = doc.AddSection(); const para = section.AddParagraph(); // Insert the section after the cover section doc.Sections.Insert(1, section) // Create an instance of the TableOfContent class and specify the switch const toc = wasmModule.TableOfContent.Create(doc, '{\\o \”1-3\” \\n 1-1}'); // Add the table of contents to the new paragraph para.Items.Add(toc); // Insert a field separator mark to the paragraph para.AppendFieldMark(wasmModule.FieldMarkType.FieldSeparator); // Insert a field end mark to the paragraph para.AppendFieldMark(wasmModule.FieldMarkType.FieldEnd); // Set the new TOC as the TOC of the document doc.TOC = toc; // Update the TOC doc.UpdateTableOfContents(); // Save the document to the VFS doc.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.Docx2019}); // Read the document from the VFS and create a Blob to trigger the download const wordArray = await wasmModule.FS.readFile(outputFileName); const blob = new Blob([wordArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `${outputFileName}`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } }; return ( <div style={{ textAlign: 'center', height: '300px' }}> <h1>Insert a Custom Table of Contents Using JavaScript in React</h1> <button onClick={InsertTOCWord} disabled={!wasmModule}> Insert and Download </button> </div> ); } export default App;
Remove the Table of Contents from a Word Document
Since TOC paragraphs have style names that start with "TOC", you can locate them by matching a regular expression on the paragraph style and then remove those paragraphs.
The detailed steps are as follows:
- Load the Spire.Doc.Base.js file to initialize the WebAssembly module.
- Fetch the Word file to the virtual file system (VFS) using the wasmModule.FetchFileToVFS() method.
- Create an instance of the Document class in the VFS using the wasmModule.Document.Create() method.
- Load the Word document from the VFS using the Document.LoadFromFile() method.
- Create an instance of the Regex class with the pattern "TOC\w+".
- Iterate through each section in the document and access its body using the Document.Sections.get_Item().Body property.
- Loop through the paragraphs in each section body and retrieve each paragraph's style via the Paragraph.StyleName property.
- Identify paragraphs whose style matches the regex using the Regex.IsMatch() method and remove them using the Section.Body.Paragraphs.RemoveAt() method.
- Save the document to the VFS using the Document.SaveToFile() method.
- Read the document from the VFS and download it.
- JavaScript
import React, { useState, useEffect } from 'react'; function App() { // State to store the loaded WASM module const [wasmModule, setWasmModule] = useState(null); // useEffect hook to load the WASM module when the component mounts useEffect(() => { const loadWasm = async () => { try { // Access the Module and spiredoc from the global window object const { Module, spiredoc } = window; // Set the wasmModule state when the runtime is initialized Module.onRuntimeInitialized = () => { setWasmModule(spiredoc); }; } catch (err) { // Log any errors that occur during module loading console.error('Failed to load the WASM module:', err); } }; // Create a script element to load the WASM JavaScript file const script = document.createElement('script'); script.src = `${process.env.PUBLIC_URL}/Spire.Doc.Base.js`; script.onload = loadWasm; // Append the script to the document body document.body.appendChild(script); // Cleanup function to remove the script when the component unmounts return () => { document.body.removeChild(script); }; }, []); // Function to remove the table of contents from a Word document const InsertTOCWord = async () => { if (wasmModule) { // Specify the input and output file names const inputFileName = 'CustomTOC.docx'; const outputFileName = 'RemoveTOC.docx'; // Fetch the input file and add it to the VFS await wasmModule.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/`); // Create an instance of the Document class const doc = wasmModule.Document.Create(); // Load the Word document doc.LoadFromFile({ fileName: inputFileName }); // Create a regex pattern to match the style name of TOC const regex = wasmModule.Regex.Create("TOC\\w+", wasmModule.RegexOptions.None); // Iterate through each section for (let i = 0; i < doc.Sections.Count; i++) { // Iterate through each paragraph in the section body const sectionBody = doc.Sections.get_Item(i).Body; for (let j = 0; j < sectionBody.Paragraphs.Count; j++) { // Check if the style name matches the regex pattern const paragraph = sectionBody.Paragraphs.get_Item(j); if (regex.IsMatch(paragraph.StyleName)) { // Remove the paragraph sectionBody.Paragraphs.RemoveAt(j) // Or remove the section //doc.Sections.RemoveAt(i) //i-- j-- } } } // Save the document to the VFS doc.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.Docx2019}); // Read the document from the VFS and create a Blob to trigger the download const wordArray = await wasmModule.FS.readFile(outputFileName); const blob = new Blob([wordArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `${outputFileName}`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } }; return ( <div style={{ textAlign: 'center', height: '300px' }}> <h1>Insert a Custom Table of Contents Using JavaScript in React</h1> <button onClick={InsertTOCWord} disabled={!wasmModule}> Insert and Download </button> </div> ); } export default App;
Get a Free License
To fully experience the capabilities of Spire.Doc for JavaScript without any evaluation limitations, you can request a free 30-day trial license.