Designing SharePoint List Forms with JSON Sections, Static Read-Only Fields, and Conditional Visibility

When a SharePoint list form starts growing, the first pain point is usually readability. A flat form with dozens of fields quickly becomes hard to scan, hard to maintain, and hard for end users to trust. The native SharePoint form JSON model helps a lot here because it lets you group columns into sections, reorder them, and mark some fields as read-only. At the same time, it has clear limits: the body configuration is strong for structure, but weak for visual styling and dynamic read-only rules. Microsoft’s form configuration model supports sections and static fieldsettings.readonly, while conditional logic in forms is documented primarily for show/hide behavior, not conditional read-only behavior. (Microsoft Learn)

In this article, I will use fully anonymized names such as Requester, Project Title, Reference Number, Approval Flag, and Objective Summary so the pattern can be reused in any tenant, blog post, or training material without exposing real client field names. This is the safest way to document production-style SharePoint customization. The examples below are based on Microsoft’s documented SharePoint declarative customization model and formatting syntax. (Microsoft Learn)


Why this pattern matters

A practical SharePoint form usually needs three things at the same time:

  1. a cleaner layout for business users,
  2. some columns that should always be locked,
  3. some columns that should only appear in certain situations.

The native SharePoint JSON form model can address all three, but each one is handled differently. Sections organize the form body, fieldsettings can make fields statically read-only, and conditional formulas can show or hide fields depending on another value or the current user. These are separate capabilities, and understanding that separation is the key to designing a maintainable solution. (Microsoft Learn)


What the native form JSON can do well

The SharePoint list form configuration model supports a sections array in the body. Each section can have a displayname and a list of fields. Microsoft also documents fieldsettings, which can be used to make named fields read-only. When body sections are configured, SharePoint switches from a simple one-column form to a multi-column layout. (Microsoft Learn)

That means native form JSON is a good fit for:

  • grouping related inputs,
  • improving navigation through long forms,
  • keeping generated or system fields locked,
  • producing a cleaner authoring experience without Power Apps. (Microsoft Learn)

What the native form JSON does not do well

The same model is limited when people try to push it into full UI design territory. The body section model does not provide per-section background styling, per-section borders, or arbitrary layout containers like the richer JSON available in column, row, or header/footer formatting. It also does not document conditional expressions for readonly; static readonly: true is supported, but conditional read-only based on another column is not part of the documented model. (Microsoft Learn)

That distinction matters a lot:

  • Body JSON is for structure.
  • Header/Footer JSON is more visual.
  • Conditional formulas are for visibility logic.
  • Power Apps or SPFx are better when you need deep UI control. (Microsoft Learn)

An anonymized body configuration example

Below is a clean, blog-safe example that groups fields into logical blocks. This is the kind of pattern I recommend when documenting SharePoint solutions publicly.

{
"sections": [
{
"displayname": "Project Overview",
"fields": [
"Requester",
"Project Title",
"Reference Number",
"Approval Flag"
]
},
{
"displayname": "1 - Business Context",
"fields": [
"Primary Request Purpose",
"Objective Summary",
"Comparison Data Available"
]
},
{
"displayname": "2 - Expected Results",
"fields": [
"Expected Deliverable"
]
},
{
"displayname": "3 - Source Information",
"fields": [
"Data Provider",
"Data Delivery Method",
"Available Supporting Documents"
]
},
{
"displayname": "4 - Conditions",
"fields": [
"Operating Conditions"
]
},
{
"displayname": "5 - Timeline",
"fields": [
"Required By Date",
"Delivery Format"
]
},
{
"displayname": "6 - Notes",
"fields": [
"Additional Notes"
]
}
]
}

This kind of structure is fully aligned with the documented form-body section model: section names for readability and field grouping for logical organization. (Microsoft Learn)


Adding static read-only fields

Now let us add a second layer: fields that should always be locked in the form. This is where fieldsettings comes in. Microsoft documents readonly as a supported property for form field settings. (Microsoft Learn)

A good real-world use case is locking fields like:

  • Requester,
  • Reference Number,
  • system-generated status values.

Here is the anonymized example:

{
"sections": [
{
"displayname": "Project Overview",
"fields": [
"Requester",
"Project Title",
"Reference Number",
"Approval Flag"
]
},
{
"displayname": "1 - Business Context",
"fields": [
"Primary Request Purpose",
"Objective Summary",
"Comparison Data Available"
]
}
],
"fieldsettings": [
{
"name": "Requester",
"readonly": true
},
{
"name": "ReferenceNumber",
"readonly": true
}
]
}

In practice, name should use the internal field name, not the friendly display label. That is an important implementation detail when you move from a blog example into a real tenant. Microsoft’s form configuration documentation describes field settings by field name, and real SharePoint implementations rely on internal names for consistency. (Microsoft Learn)


The big limitation: conditional read-only is not documented

This is where many SharePoint implementations hit a wall. A very common business request is:

  • “Make these fields read-only after the item is submitted.”
  • “Make these fields read-only for everyone except one coordinator.”
  • “Make the field editable only while status is Draft.”

The native form model does not document a conditional expression syntax for readonly. It documents static readonly, but not readonly formulas like =if([$ApprovalFlag] == true, true, false). So while the idea is natural, it is not part of the documented native capability. (Microsoft Learn)

That means this kind of pattern should be avoided in production documentation because it suggests support that is not officially documented:

{
"fieldsettings": [
{
"name": "ProjectTitle",
"readonly": "=if([$ApprovalFlag] == true, true, false)"
}
]
}

For blog readers, this is an important architectural lesson: do not confuse native static read-only with dynamic business-state locking. (Microsoft Learn)


The supported workaround: conditional visibility

The supported workaround is to use conditional show/hide formulas in the form experience. SharePoint’s formatting syntax supports Excel-style expressions, references to fields like [$ColumnName], and special tokens like @me for the current user. Microsoft’s syntax reference documents these expression patterns, and the form experience supports conditional visibility formulas. (Microsoft Learn)

This means you can do something very useful even if you cannot do true conditional read-only.

Example: hide a field after approval

=if([$ApprovalFlag] == true, 'false', 'true')

This formula means:

  • if the approval flag is true, hide the field,
  • otherwise, show it. (Microsoft Learn)

It is not the same as read-only, but from a process perspective it often solves the same business problem: users stop editing the field once the item is considered submitted or approved. (Microsoft Learn)


User-based visibility with @me

Another strong pattern is showing a field only to a specific person, reviewer, or coordinator. SharePoint formatting syntax supports @me, which lets expressions compare the current user to another value. Microsoft documents @me as part of the formatting expression language. (Microsoft Learn)

For example, to show an editable field only to a single designated user:

=if(@me == 'reviewer@contoso.com', 'true', 'false')

And to combine user logic with process-state logic:

=if(@me == 'reviewer@contoso.com' && [$ApprovalFlag] != true, 'true', 'false')

This is one of the most useful native patterns in SharePoint forms because it gets very close to “editable only for one person until submission,” even though it is technically implemented as conditional visibility, not conditional read-only. (Microsoft Learn)


Why anonymization improves technical documentation

Using anonymized field names is not only about privacy. It also makes your documentation more reusable. A reader can understand the pattern immediately:

  • Requester instead of a real employee field,
  • Project Title instead of a client-specific business term,
  • Approval Flag instead of a tenant-specific boolean,
  • Reference Number instead of a proprietary identifier.

This produces a cleaner learning artifact and keeps the article focused on architecture rather than tenant-specific details. It is especially useful for SharePoint blog posts because the real educational value is in the pattern, not the original column labels. This is an implementation best practice and a documentation best practice, even though it is not a Microsoft feature itself. The underlying SharePoint capabilities still come from the documented form configuration and syntax model. (Microsoft Learn)


Recommended design pattern for production teams

For most teams, the best native design pattern looks like this:

  • use body sections to make the form readable,
  • use fieldsettings.readonly only for fields that are always locked,
  • use conditional formulas for show/hide behavior,
  • use @me for reviewer-specific visibility,
  • move to Power Apps or SPFx only when you truly need richer interaction or styling. (Microsoft Learn)

This gives you a practical balance between simplicity, maintainability, and user experience. It also keeps the solution inside the native SharePoint model for as long as possible. (Microsoft Learn)


A complete anonymized example for a blog

Below is a realistic, publishable example that shows the structure and the static lock pattern together.

{
"sections": [
{
"displayname": "Project Overview",
"fields": [
"Requester",
"Project Title",
"Reference Number",
"Approval Flag"
]
},
{
"displayname": "1 - Business Context",
"fields": [
"Primary Request Purpose",
"Objective Summary",
"Comparison Data Available"
]
},
{
"displayname": "2 - Expected Results",
"fields": [
"Expected Deliverable"
]
},
{
"displayname": "3 - Source Information",
"fields": [
"Data Provider",
"Data Delivery Method",
"Available Supporting Documents"
]
},
{
"displayname": "4 - Conditions",
"fields": [
"Operating Conditions"
]
},
{
"displayname": "5 - Timeline",
"fields": [
"Required By Date",
"Delivery Format"
]
},
{
"displayname": "6 - Notes",
"fields": [
"Additional Notes"
]
}
],
"fieldsettings": [
{
"name": "Requester",
"readonly": true
},
{
"name": "ReferenceNumber",
"readonly": true
}
]
}

And then, outside this JSON, you can configure field-level conditional visibility such as:

=if([$ApprovalFlag] == true, 'false', 'true')

or:

=if(@me == 'reviewer@contoso.com' && [$ApprovalFlag] != true, 'true', 'false')

The separation is important: read-only is configured in form JSON, while conditional visibility is configured through form conditional formulas using SharePoint expressions. (Microsoft Learn)


Final thoughts

This style of SharePoint form customization is not flashy, but it is extremely effective. It respects the platform instead of fighting it. Native JSON body formatting gives you a clean way to transform a long, chaotic form into a structured experience. Static read-only settings help protect system-owned fields. Conditional visibility formulas add process awareness and user awareness. Once you understand the line between those three capabilities, your SharePoint forms become far easier to design and document. (Microsoft Learn)

The most important takeaway is simple: use native JSON for structure, use conditional formulas for visibility, and do not expect native conditional read-only behavior unless you move to a richer customization model. (Microsoft Learn)

Step-by-step implementation table

StepGoalNative featureExample
1Organize the form into logical blockssectionsProject Overview, Business Context, Timeline
2Keep system-owned fields lockedfieldsettings.readonlyRequester, ReferenceNumber
3Prevent editing after submissionConditional visibility=if([$ApprovalFlag] == true, 'false', 'true')
4Show fields only to a specific reviewer@me expression=if(@me == 'reviewer@contoso.com', 'true', 'false')
5Combine process state and user logic@me + field comparison=if(@me == 'reviewer@contoso.com' && [$ApprovalFlag] != true, 'true', 'false')
6Keep blog documentation reusableAnonymizationReplace real field names with neutral placeholders

Technical summary table

CapabilitySupported nativelyNotes
Group fields into body sectionsYesDocumented in SharePoint form configuration. (Microsoft Learn)
Static read-only fieldsYesSupported through fieldsettings.readonly. (Microsoft Learn)
Conditional read-onlyNo documented native supportUse conditional visibility instead. (Microsoft Learn)
Conditional show/hide formulasYesUses SharePoint expression syntax. (Microsoft Learn)
Current-user logic with @meYesSupported by formatting syntax. (Microsoft Learn)
Per-section body background stylingNot part of the documented body-section modelBetter handled in header/footer or richer customizations. (Microsoft Learn)
Full UI controlNot with native form body JSONPower Apps or SPFx is the next step. (Microsoft Learn)

Edvaldo Guimrães Filho Avatar

Published by