evont-software.com
For classic SharePoint 2019 libraries you still need your EditForm.aspx and DispForm.aspx to edit your properties. If you like to make any changes, create another form page or repair it by code, it is a little bit more complicated. Most time you try to edit the "DefaultEditFormUrl" property of your list. If you try to change the "DefaultEditFormUrl" property it leads some time to the following error:
Unable to find an SPForm matching URL...
The reason is, sharepoint evaluates your target url and try to find the form on the page. So you have also to upload the list form webpart.
Here i show some helpers to realise this with javascript code. Most samples on internet are powershell, but doing this in a SPFX solution it is also very smart. We use here some help from pnp js (https://pnp.github.io/pnpjs/) framework. You can download the content of the aspx file from a existing library by open your folder in internet explorer and copy the file.
1const folderUrl = '/sites/sitecollection/library/';2const dispFormUrl = `${folderUrl}/Forms/EditForm.aspx`;3const content = `..........`; //replace your content4await this.uploadFile(folderUrl, dispFormUrl, content);56/**7 * Upload a file from a library8 *9 * @param folderUrl relative path of a library or the folder in a library10 * @param fileUrl new relative url of the file11 * @param content content of the file12 */13public async uploadFile(folderUrl: string, fileUrl: string, content: Blob | ArrayBuffer | string): Promise<void> {14 const props: IAddUsingPathProps = { Overwrite: true };15 await sp.web.getFolderByServerRelativeUrl(folderUrl).files.addUsingPath(fileUrl, content, props);16}
You need to import the list webpart, don't forget to set the listid. Your class should also have a property for spHttpClient and absoluteWebUrl from pnp js.
1const listInfoId:string = 'xxxxx-xx-xxxx-..';23const editwebpartxml = `<?xml version="1.0" encoding="utf-8"?>4 <WebPart xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/WebPart/v2">5 <Title />6 <FrameType>Default</FrameType>7 <Description />8 <IsIncluded>true</IsIncluded>9 <ZoneID>Main</ZoneID>10 <PartOrder>1</PartOrder>11 <FrameState>Normal</FrameState>12 <Height />13 <Width />14 <AllowRemove>true</AllowRemove>15 <AllowZoneChange>true</AllowZoneChange>16 <AllowMinimize>true</AllowMinimize>17 <AllowConnect>true</AllowConnect>18 <AllowEdit>true</AllowEdit>19 <AllowHide>true</AllowHide>20 <IsVisible>true</IsVisible>21 <DetailLink />22 <HelpLink />23 <HelpMode>Modeless</HelpMode>24 <Dir>Default</Dir>25 <PartImageSmall />26 <MissingAssembly>Dieses Webpart kann nicht importiert werden.</MissingAssembly>27 <PartImageLarge />28 <IsIncludedFilter />29 <Assembly>Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>30 <TypeName>Microsoft.SharePoint.WebPartPages.ListFormWebPart</TypeName>31 <ListName xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">{${listInfoId}}</ListName>32 <ListId xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">${listInfoId}</ListId>33 <PageType xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">PAGE_EDITFORM</PageType>34 <FormType xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">6</FormType>35 <ControlMode xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">Edit</ControlMode>36 <ViewFlag xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">1048576</ViewFlag>37 <ViewFlags xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">Default</ViewFlags>38 <ListItemId xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">0</ListItemId>39 </WebPart>`;4041const displaywebpartxml = `<?xml version="1.0" encoding="utf-8"?>42 <WebPart xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/WebPart/v2">43 <Title />44 <FrameType>Default</FrameType>45 <Description />46 <IsIncluded>true</IsIncluded>47 <ZoneID>Main</ZoneID>48 <PartOrder>1</PartOrder>49 <FrameState>Normal</FrameState>50 <Height />51 <Width />52 <AllowRemove>true</AllowRemove>53 <AllowZoneChange>true</AllowZoneChange>54 <AllowMinimize>true</AllowMinimize>55 <AllowConnect>true</AllowConnect>56 <AllowEdit>true</AllowEdit>57 <AllowHide>true</AllowHide>58 <IsVisible>true</IsVisible>59 <DetailLink />60 <HelpLink />61 <HelpMode>Modeless</HelpMode>62 <Dir>Default</Dir>63 <PartImageSmall />64 <MissingAssembly>Dieses Webpart kann nicht importiert werden.</MissingAssembly>65 <PartImageLarge />66 <IsIncludedFilter />67 <Assembly>Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>68 <TypeName>Microsoft.SharePoint.WebPartPages.ListFormWebPart</TypeName>69 <ListName xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">{${listInfoId}}</ListName>70 <ListId xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">${listInfoId}</ListId>71 <PageType xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">PAGE_DISPLAYFORM</PageType>72 <FormType xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">4</FormType>73 <ControlMode xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">Display</ControlMode>74 <ViewFlag xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">1048576</ViewFlag>75 <ViewFlags xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">Default</ViewFlags>76 <ListItemId xmlns="http://schemas.microsoft.com/WebPart/v2/ListForm">0</ListItemId>77 </WebPart>`;787980await this.importClassicPageWebpart(dispFormUrl, 'Main', 1, displaywebpartxml);81await this.importClassicPageWebpart(editFormUrl, 'Main', 1, editwebpartxml);828384/**85 * Imports webpart on classic page86 * @param pageUrl87 * @param zone Main88 * @param order 189 * @param webpartxml90 * @returns91 */92public async importClassicPageWebpart(93 pageUrl: string,94 zone: string,95 order: number,96 webpartxml: string97): Promise<void> {98 const webid = (await sp.web.get()).Id;99 const siteid = (await sp.site.get()).Id;100 webpartxml = this.encodeXml(webpartxml);101 const requestBody = `<?xml version="1.0" encoding="UTF-8"?>102 <Request103 xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0" ApplicationName="Javascript Library">104 <Actions>105 <ObjectPath Id="41" ObjectPathId="40" />106 <ObjectPath Id="43" ObjectPathId="42" />107 <ObjectIdentityQuery Id="44" ObjectPathId="42" />108 <ObjectPath Id="46" ObjectPathId="45" />109 <ObjectPath Id="48" ObjectPathId="47" />110 <ObjectIdentityQuery Id="49" ObjectPathId="47" />111 <Query Id="50" ObjectPathId="45">112 <Query SelectAllProperties="true">113 <Properties />114 </Query>115 </Query>116 </Actions>117 <ObjectPaths>118 <Method Id="40" ParentId="28" Name="GetLimitedWebPartManager">119 <Parameters>120 <Parameter Type="Number">1</Parameter>121 </Parameters>122 </Method>123 <Method Id="42" ParentId="40" Name="ImportWebPart">124 <Parameters>125 <Parameter Type="String">${webpartxml}</Parameter>126 </Parameters>127 </Method>128 <Property Id="45" ParentId="42" Name="WebPart" />129 <Method Id="47" ParentId="40" Name="AddWebPart">130 <Parameters>131 <Parameter ObjectPathId="45" />132 <Parameter Type="String">${zone}</Parameter>133 <Parameter Type="Number">${order}</Parameter>134 </Parameters>135 </Method>136 <Identity Id="28" Name="82d7c99e-f015-0000-6402-fdbb9f2aa54d|740c6a0b-85e2-48a0-a494-e0f1759d4aa7:site:${siteid}:web:${webid}:file:${pageUrl}" />137 </ObjectPaths>138</Request>`;139 return await this.postcsom(requestBody).then((result) => {140 if (result[0].ErrorInfo !== null) {141 throw new Error(JSON.stringify(result[0].ErrorInfo));142 }143 return;144 });145}146147148/**149 * xml encodes a string150 * @param str151 * @returns152 */153private encodeXml(str: string): string {154 const xml_special_to_escaped_one_map = {155 '&': '&',156 '"': '"',157 '<': '<',158 '>': '>'159 };160161 return str.replace(/([\&"<>])/g, function (str, item) {162 return xml_special_to_escaped_one_map[item];163 });164}165166167168169/**170 * sends a request to client svc171 * @param data request data172 */173private async postcsom(data: string): Promise<any> {174 const clientServiceUrl = this.absoluteWebUrl + '/_vti_bin/client.svc/ProcessQuery';175176 const formDigest = await this.getFormDigest();177178 const requestHeaders: Headers = new Headers();179 requestHeaders.append('Accept', 'application/json');180 requestHeaders.append('Content-Type', 'text/xml');181 requestHeaders.append('X-RequestDigest', formDigest);182183 const httpPostOptions: IHttpClientOptions = {184 headers: requestHeaders,185 body: data186 };187188 const serviceResponse: IResponse = await this.spHttpClient.post(clientServiceUrl,SPHttpClient.configurations.v1, httpPostOptions);189 const serviceJSONResponse = await serviceResponse.json();190 if (serviceResponse.ok) {191 return serviceJSONResponse;192 }193 return null;194}195196/**197 * digest is needed for post requests198 */199private async getFormDigest(): Promise<string> {200 const contextInfoUrl = this.absoluteWebUrl + '/_api/contextinfo';201202 const requestHeaders: Headers = new Headers();203 requestHeaders.append('Accept', 'application/json');204 requestHeaders.append('Content-Type', 'text/xml');205206 const httpPostOptions: IHttpClientOptions = {207 headers: requestHeaders208 };209 const contextInfoResponse: IResponse = await this.spHttpClient.post(contextInfoUrl, httpPostOptions);210 const contextInfoJsonResponse = await contextInfoResponse.json();211 const formDigest: string = contextInfoJsonResponse.FormDigestValue;212213 return formDigest;214}
Finally you can update your list form without errors.
1await this.updateList(listTitle, {2 DefaultDisplayFormUrl: dispFormUrl,3 DefaultEditFormUrl: editFormUrl,4 ContentTypesEnabled: false5 });67/**8 * Updates List Properties9 * @param listTitle10 * @param properties of type IListInfo possible11 */12public async updateList(listTitle: string, properties: Record<string, unknown>): Promise<void> {13 await sp.web.lists.getByTitle(listTitle).update(properties);14}
By the way, you see also a easy method how to interact with jsom api, without having the complete api included.