SharePoint / sp-dev-docs

SharePoint & Viva Connections Developer Documentation
https://docs.microsoft.com/en-us/sharepoint/dev/
Creative Commons Attribution 4.0 International
1.25k stars 1.01k forks source link

Removing faulty form custom body json #6738

Open djbove opened 3 years ago

djbove commented 3 years ago

When saving a form custom body json in a list form on Sharepoint online that renders the whole list form blank, there seems to be no way to reset or remove the json again to the Sharepoint default form layout. I inserted json with a handful of sections listing all list fields and when previewing it rendered a blank form with no list fields and not showing the input field for the json- which I accidentally saved! My bad! Now I don’t seem to have a way to remove the faulty Json, as when opening the form it’s blank with no possibility to see any list fields or any customisation possibilities.

I desperately need access to editing the list data again with the list form.

best regards Peter


Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

ghost commented 3 years ago

Thank you for reporting this issue. We will be triaging your incoming issue as soon as possible.

bcameron1231 commented 3 years ago

Are you saying the configure layout button is now missing?

markpandrew commented 3 years ago

Regrettably I've suffered this exact same fault. MS are telling me this is "out of support for SharePoint online" which I am simply dumbfounded by. How can it be possible to nuke functionality of editing/viewing list data through a mistake in the JSON and for support to wash their hands of it?

I'm hopeful that someone here may have some ideas on how to resolve.

To answer @bcameron1231 the configure layout option does appear at the very top of a blank form where previously all my datafields were displayed. Clicking it opens a further blank form over the top, you have to click the X close button twice to get back to the list.

If @djbove was able to solve this I'd be very interested in the method.

bcameron1231 commented 3 years ago

I guess I'm trying to repro the issue. Do you have a sample JSON that you used I could try out?

markpandrew commented 3 years ago

It was something along these lines, very close to the example directly linked from the site. The tweak I made at the very end was to only add a displayname section without the fields, anticipating it would leave a larger format header in bold text above the last section which lists attachments. I strongly suspect this broke it, but it did of course pass whatever limited parsing of the JSON that the system does to validate it. The tweaks I had made prior to this were working fine. I will add this is my best attempt to recreate it from cut/paste history and isn't exactly as was used - I don't have a copy of that. I was lulled into a safe place just figuring I could play around tweaking it until I got the result I needed! Very appreciative of you taking the time to look at this.

{ "sections": [ { "displayname": "Pack Details", "fields": [ "Reference", "Pack Serial Number", "Pack No" ] }, { "displayname": "Investigation Stage", "fields": [ "Status", "Customer Fault Description", "Diagnosed Fault/s" ] }, { "displayname": "Diagnosis", "fields": [ "Diagnosis" ] }, { "displayname": "More Fields", "fields": [ "Repairs Reqd", "Root Cause" ] }, { "displayname": "File Attachments" ] } ] }

bcameron1231 commented 3 years ago

Okay, great. Just so you know that JSON isn't valid... you have an extra ] bracket after file attachments.

Now, it appears the issue is because you are missing the "fields" values under displayname... so you haven't specified any, thus it is breaking and showing a blank screen.

What it appears, is that the JSON doesn't actually save. But you are right, it renders a blank screen.

But this doesn't stop me from re-configuring my layout. You need to hit the 'X' in the top right, and then select "Configure Layout" again. You can't select Configure Layout from the Configure Layout Screen (frankly, that button should be hidden in my opinion).

I am unable to reproduce the issue where It goes blank, and then when I create new items... it's still blank...

markpandrew commented 3 years ago

As I posted it I figured the JSON was wrong, it's obvious in hindsight of course! The tricky part is that it did save the broken JSON and now has stuck without giving me any way to correct it. Even creating new items in the list using the +New button results in a blank form now that can't be filled in. Workaround at the moment is to use the Classic Experience which then does allow viewing/editing. Also note that if the (i) button is clicked when an item is selected to open the details pane, this fails with a "Something went wrong, Cannot read property 'indexOf' of undefined" error. Customize with Power Apps does work and may be the unpleasant way out of this, by creating a PowerApp to render the form data but this is a huge step up in complexity when all I wanted was to rearrange some fields!

bcameron1231 commented 3 years ago

Alright, I have been able to reproduce on another list. It does seem there are scenarios where you add JSON to the page, which is valid JSON but does not match the schema of the formatting required, it can save and it stops it from rending.

@chakkaradeep I'm not sure if you are aware of this issue.... but it does pose a problem.

I've been able to reproduce by adding a JSON format to the body section of a form. I include a displayname, but do not add FIelds property. It is respected as valid JSON, it will save, but it will completely break the form.

I do notice errors on the browser dev console that show up when loading the broken form. image

@markpandrew and @djbove I do have a fix.... albeit it's a little convoluted. But we can fix this using the REST API.

  1. Update the URL to your Tenant and Library Below
  2. Update the GetbyTitle('Demo') to the display name of your list
  3. Grab the content type from your list a. Go to list, advanced, enable content types b. Open up content type, and grab the Content Type ID from the URL c. Replace Content Type in lower command
  4. Open up developer tools in your Browser using F12
  5. Go to the Console, paste in the updated code below with your settings and hit enter.

fetch("https://YourTenant.sharepoint.com/sites/JSON-Formatting/_api/contextinfo", {
  "headers": {
    "accept": "application/json;odata=verbose",
    "accept-language": "en-US,en;q=0.9",
    "content-type": "application/json;odata=verbose",
 },
  "method": "POST",
  "mode": "cors",
}).then(response => response.json())
.then((data)=>{

    fetch("https://yourtenant.sharepoint.com/sites/JSON-Formatting/_api/web/lists/getbytitle('Demo')/contentTypes('0x0100F566899D669FFB4D9CA9135D63C98EAB001D365D0D20AF3E478A1E321ACB5C901F')", {
      "headers": {
        "accept": "application/json;odata=verbose",
        "accept-language": "en-US,en;q=0.9",
        "content-type": "application/json;odata=verbose",
        "x-requestdigest": data.d.GetContextWebInformation.FormDigestValue
      },
      "body": "{\"__metadata\":{\"type\":\"SP.ContentType\"},\"ClientFormCustomFormatter\":\"\"\}",
      "method": "MERGE",
      "mode": "cors",
      "credentials": "include"
    });

}        
);

What this code does, is get a digest token in order to be able to update your content type formatting. Then, the second request sets the ClientFOrmCustomFormatter to empty and removes the formatting you have in place.

markpandrew commented 3 years ago

@bcameron1231 Just wow, what brilliant effort, thank you so much. Not quite there for me, but presumably a mistake on my part. Here's what I did. Went to List Settings from the cog top right, then Advanced settings, turned on "Allow management of content types?" to Yes. Back to List Settings and clicked "Item" hyperlink underneath new Content Type table. URL of this page is:

https://mycompany.sharepoint.com/sites/power/_layouts/15/ManageContentType.aspx?List=%7B29527988%2DD3BE%2D4866%2D9130%2D1445B696B65A%7D&ctype=0x010047A5DDD91CE4F5478FBE51E112431EEC

so pasted 0x010047A5DDD91CE4F5478FBE51E112431EEC into second fetch command to replace what is there in the brackets, i.e. fetch("https://mycompany.sharepoint.com/sites/JSON-Formatting/_api/web/lists/getbytitle('Customer 400 Returns')/contentTypes('0x010047A5DDD91CE4F5478FBE51E112431EEC')", { and so on.

Note my site list name has spaces unhelpfully, should this be replaced with %20 instead?

Anyway, when pasted into F12>Console using Edge or Chrome results in: image

Could be my site is a sub-site? i.e. url is company.sharepoint.com/sites/power/Lists/Customer%20400%20Returns/All%20Items.aspx?.....

This error appears when trying to open the form: image Thanks again for your continued patience and support.

bcameron1231 commented 3 years ago

Yup. Your site name is wrong. I have mine at json-formatting. Yours should be "sites/power". ( I Should have clarified you need to replace the site relative url, not the Tenant only)

markpandrew commented 3 years ago

@bcameron1231 Brilliant, all back. I'm so grateful you've got me out of a real sticky situation. I note you've copied in @chakkaradeep to highlight this beartrap for the less talented Sharepoint meddlers among us, here's hoping something can be tweaked to prevent others getting caught in the seemingly inescapable loop I found myself in. Wish you well.

NMT-mgagne commented 1 year ago

I tried the above and it didn't work for me.

I had a badly formatted JSON for the view format which I accidentally saved (Whoops!). Whenever that view was accessed, the screen would be completely blank (no SharePoint headers, nothing). I had only one view in the list called "All Items" (default).

I was able to recover my list by basically creating a new view and deleting the old one.

  1. Navigate to the main site
  2. Click the settings (gear icon) -> Site Information -> View all site settings
  3. Under Site Administration, click Site libraries and lists
  4. Click Customize "name of your list"
  5. At the bottom of the page click -> Create view
  6. Give the view a random name and set all of its settings as required
  7. Make the new view the default view (the broken view can't be default otherwise it can't be deleted)
  8. Back in the list settings, click the name of the broken view
  9. At the bottom of the screen, click the delete button

This approach took some work but at least avoided me losing all of my list item data and needing to redo any linking that I had setup in Power Automate.

maexrock commented 1 year ago

Some hours later, but @bcameron1231, your hint is still valid and was very useful to help me out.

I've got my JSON broken while i was trying to embed a href link as a section name, no chance to get out of rendering issues via the web interface, form was blank.

During my investigations i was able to use your solution with one little but important change:

→ contentTypes('0x0100F566899D669FFB4D9CA9135D63C98EAB001D365D0D20AF3E478A1E321ACB5C901F') was not valid for my case

fetch("https://YourTenant.sharepoint.com/sites/mysite/_api/contextinfo", {
  "headers": {
    "accept": "application/json;odata=verbose",
    "accept-language": "en-US,en;q=0.9",
    "content-type": "application/json;odata=verbose",
 },
  "method": "POST",
  "mode": "cors",
}).then(response => response.json()).then((data)=>{
    fetch("https://YourTenant.sharepoint.com/sites/mysite/_api/web/lists/getbytitle('mylist')", {
      "headers": {
        "accept": "application/json;odata=verbose",
        "accept-language": "en-US,en;q=0.9",
        "content-type": "application/json;odata=verbose",
        "x-requestdigest": data.d.GetContextWebInformation.FormDigestValue
      },
      "method": "POST",
      "mode": "cors",
      "credentials": "include"
    }).then(response => response.json()).then((data)=>{console.log(data)});
}        
);

delivers d.ContentTypes.__deferred.uri which leads me to:

...
<content type="application/xml">
<properties>
<ClientFormCustomFormatter>
...
<Id m:type="SP.ContentTypeId">
    <StringValue>
        0x01000AC41DE60062DB408253A5C45D314A60006AC84011DADFD3409FD1B137E6A22EE9
    </StringValue>
</Id>
...

With this value i was able to reset the JSON formatting:

fetch("https://YourTenant.sharepoint.com/sites/mysite/_api/contextinfo", {
  "headers": {
    "accept": "application/json;odata=verbose",
    "accept-language": "en-US,en;q=0.9",
    "content-type": "application/json;odata=verbose",
 },
  "method": "POST",
  "mode": "cors",
}).then(response => response.json()).then((data)=>{
    fetch("https://YourTenant.sharepoint.com/sites/mysite/_api/web/lists/getbytitle('mylist')/contentTypes('0x01000AC41DE60062DB408253A5C45D314A60006AC84011DADFD3409FD1B137E6A22EE9')", {
      "headers": {
        "accept": "application/json;odata=verbose",
        "accept-language": "en-US,en;q=0.9",
        "content-type": "application/json;odata=verbose",
        "x-requestdigest": data.d.GetContextWebInformation.FormDigestValue
      },
      "body": "{\"__metadata\":{\"type\":\"SP.ContentType\"},\"ClientFormCustomFormatter\":\"\"\}",
      "method": "MERGE",
      "mode": "cors",
      "credentials": "include"
    }).then(response => response.json()).then((data)=>{console.log(data)});
}        
);

Thanks again @bcameron1231 !!!

bcameron1231 commented 1 year ago

@maexrock Glad it helped you!