NextJS/JSS Edit Frames Before JSS v21.1.0

> It is possible. We have the technology.
Cover Image for NextJS/JSS Edit Frames Before JSS v21.1.0

Overview

I wanted to implement edit Frames on a NextJS/TS/JSS v20.1.3 site. I was disappointed to find out that official support for edit frames was only added in v21.1.0, so I went out looking for other options.

Why Edit Frames?

Edit frames are a useful tool for content authors to edit arbitrary fields on arbitrary items via arbitrarily placed clickable elements on a page. One example would be if you wanted a way for a user to edit a background image on a section. You might render an absolutely positioned clickable icon that would allow the background image field to be edited. The possibilities are endless.

The Implementation

I was inspired by this SSE post about possible solutions: https://sitecore.stackexchange.com/questions/24307/edit-frame-with-sitecore-jss.

One of the answers points to a custom implementation of edit frames that someone wrote ~3.5 years before Sitecore added official support for it 👀: https://github.com/Sitecore/jss/pull/290. I refactored / modernized the code to work with strict TypeScript and the latest React patterns.

The Code


_84
import React from 'react';
_84
import { useSitecoreContext } from '@sitecore-jss/sitecore-jss-nextjs';
_84
_84
interface FieldEditFrameProps {
_84
itemId?: string;
_84
fields?: string[];
_84
header?: string;
_84
icon?: string;
_84
disabledIcon?: string;
_84
tooltip?: string;
_84
command?: string;
_84
commandDisplayName?: string;
_84
databaseName?: string;
_84
language?: string;
_84
hideIfNotPageEditing?: boolean;
_84
}
_84
_84
const FieldEditFrame: React.FC<FieldEditFrameProps> = ({
_84
itemId = '',
_84
fields = [],
_84
header = 'Edit Fields',
_84
icon = '/temp/iconcache/people/16x16/cubes_blue.png',
_84
disabledIcon = '/temp/cubes_blue_disabled16x16.png',
_84
tooltip,
_84
command = '{70C4EED5-D4CD-4D7D-9763-80C42504F5E7}',
_84
commandDisplayName,
_84
databaseName,
_84
language,
_84
hideIfNotPageEditing,
_84
children,
_84
}) => {
_84
const { sitecoreContext } = useSitecoreContext();
_84
const { pageEditing, language: sitecoreLanguage, route } = sitecoreContext;
_84
const shouldRender = pageEditing && itemId && fields && fields.length;
_84
_84
if (!shouldRender && hideIfNotPageEditing) {
_84
return null;
_84
}
_84
_84
if (!itemId || !fields) {
_84
return null;
_84
}
_84
_84
// TODO: handle route undefined
_84
const contextItemUri = `sitecore://${databaseName || route?.databaseName}/${itemId}?lang=${
_84
language || sitecoreLanguage
_84
}`;
_84
_84
const clickCommandAction = `webedit:fieldeditor(command=${command},fields=${fields.join(
_84
'|'
_84
)},id=${itemId})`;
_84
_84
const clickCommand = {
_84
click: `javascript:Sitecore.PageModes.PageEditor.postRequest('${clickCommandAction}',null,false)`,
_84
header: header,
_84
icon: icon,
_84
disabledIcon: disabledIcon,
_84
isDivider: false,
_84
tooltip: tooltip || `Edit the following fields: ${fields.join(', ')}`,
_84
type: null,
_84
};
_84
_84
const commandData = {
_84
commands: [clickCommand],
_84
contextItemUri: contextItemUri,
_84
custom: {},
_84
displayName: commandDisplayName || 'Edit Properties',
_84
expandedDisplayName: '',
_84
};
_84
_84
const divAttrs = {
_84
sc_item: contextItemUri,
_84
'sc-part-of': 'editframe',
_84
};
_84
_84
return (
_84
<div className="scLooseFrameZone scEnabledChrome" {...divAttrs}>
_84
<span className="scChromeData">{JSON.stringify(commandData)}</span>
_84
{children}
_84
</div>
_84
);
_84
};
_84
_84
export default FieldEditFrame;

Example Implementation


_15
import FieldEditFrame from './../../utils/FieldEditFrame';
_15
_15
// other code
_15
_15
return (
_15
<>
_15
<FieldEditFrame
_15
// of course, its better not to hardcode these values
_15
itemId="{FEA43559-D12F-47C9-911C-8170B7FAEFA4}"
_15
fields={['Alert Label']}
_15
>
_15
<h2>Goo Goo Ga Ga</h2>
_15
</FieldEditFrame>
_15
</>
_15
);

Now the element is clickable: Edit fields popup

And clicking the blocks icon opens the field editor window: Field editor window

Further Steps

Be sure to do some extra testing on your local:

  • How does it behave during hot reloads?
  • Any console errors?
  • Does it work with multiple edit frames on the same page?

Build or beg,

Marcel


More Stories

Cover Image for Sitecore Symposium 2022

Sitecore Symposium 2022

> What I'm Watching 👀

Cover Image for Tips for New Sitecore Developers

Tips for New Sitecore Developers

> If I had more time, I would have written a shorter letter

Cover Image for Content Editor Search Bar Not Working

Content Editor Search Bar Not Working

> Sometimes it works, sometimes not

Cover Image for Ideas For Docker up.ps1 Scripts

Ideas For Docker up.ps1 Scripts

> Because Docker can be brittle

Cover Image for On Sitecore Stack Exchange (SSE)

On Sitecore Stack Exchange (SSE)

> What I've learned, what I see, what I want to see

Cover Image for How to Run Old Versions of Solr in a Docker Container

How to Run Old Versions of Solr in a Docker Container

> Please don't make me install another version of Solr on my local...

Cover Image for Azure PaaS Cache Optimization

Azure PaaS Cache Optimization

> App Services benefit greatly from proper configuration

Cover Image for Security Series: App Service IP Restrictions

Security Series: App Service IP Restrictions

> How to manage IP rules "at scale" using the Azure CLI

Cover Image for Add TypeScript Type Checks to RouteData fields

Add TypeScript Type Checks to RouteData fields

> Inspired by error: Conversion of type may be a mistake because neither type sufficiently overlaps with the other.

Cover Image for JSS + TypeScript Sitecore Project Tips

JSS + TypeScript Sitecore Project Tips

> New tech, new challenges

Cover Image for JSS: Reducing Bloat in Multilist Field Serialization

JSS: Reducing Bloat in Multilist Field Serialization

> Because: performance, security, and error-avoidance

Cover Image for Troubleshooting 502 Responses in Azure App Services

Troubleshooting 502 Responses in Azure App Services

> App Services don't support all libraries

Cover Image for Symposium 2022 Reflections

Symposium 2022 Reflections

> Sitecore is making big changes

Cover Image for Super Fast Project Builds with Visual Studio Publish

Super Fast Project Builds with Visual Studio Publish

> For when solution builds take too long

Cover Image for NextJS: Short URL for Viewing Layout Service Response

NextJS: Short URL for Viewing Layout Service Response

> Because the default URL is 2long4me

Cover Image for Don't Ignore the HttpRequestValidationException

Don't Ignore the HttpRequestValidationException

> Doing so could be... potentially dangerous

Cover Image for Early Returns in React Components

Early Returns in React Components

> When and how should you return early in a React component?

Cover Image for On Mentorship and Community Contributions

On Mentorship and Community Contributions

> Reflections and what I learned as an MVP mentor

Cover Image for Tips for Applying Cumulative Sitecore XM/XP Patches and Hotfixes

Tips for Applying Cumulative Sitecore XM/XP Patches and Hotfixes

> It's probably time to overhaul your processes

Cover Image for Critical Security Bulletin SC2024-001-619349 Announced

Critical Security Bulletin SC2024-001-619349 Announced

> And other scintillating commentary

Cover Image for Script: Boost SIF Certificate Expiry Days

Script: Boost SIF Certificate Expiry Days

> One simple script that definitely won't delete your system32 folder

Cover Image for SPE Script Performance & Troubleshooting

SPE Script Performance & Troubleshooting

> Script never ends or runs too slow? Get in here.

Cover Image for Tips for Forms Implementations

Tips for Forms Implementations

> And other pro tips

Cover Image for NextJS: Access has been blocked by CORS policy

NextJS: Access has been blocked by CORS policy

> CORS is almost as much of a nuisance as GDPR popups

Cover Image for Year in Review: 2022

Year in Review: 2022

> Full steam ahead

Cover Image for On Sitecore Development

On Sitecore Development

> Broadly speaking

Cover Image for Hello World

Hello World

> Welcome to the show

Cover Image for NextJS: Unable to Verify the First Certificate

NextJS: Unable to Verify the First Certificate

> UNABLE_TO_VERIFY_LEAF_SIGNATURE