How to Create a Preview Button in Strapi v3 for Next.js

Quadri Sheriff, aspiring technical writer, software programmer and Amir Tadrisi, fullstack engineer who love the challenges of working with cutting-edge technologies wrote great articles; Implementing Previews with Next Applications using a Strapi backend & How to use Image and preview in your Nextjs - Strapi blog about using the preview system of Next.js with Strapi.


This is a companion discussion topic for the original entry at https://strapi.io/blog/create-a-preview-button-in-strapi-v3-for-next-js

Hi, thanks for this usefull tutorials,
Now we are on v4 we should use things like :

app.injectContentManagerComponent("editView", "right-links", {
      name: "my-plugin-my-compo",
      Component: () => "my-compo",
    });

instead of

 {
  plugin: 'content-manager.editView',
  area: 'right.links',
  component: ExternalLink,
  key: 'content-manager.preview-link',
},

What would be the equivalent for (and is their somewhere a list of different possibility - i don’t see it in the doc) :

{
   plugin: 'content-type-builder.listView',
   area: 'list.link',
   component: ConfigureViewButton,
   key: 'content-manager.link',
},

I hope you could have time to re-write a bit this tutorials.
Thanks for awesome work :smiley:

When implementing this, I sometimes get the below error when opening the edit view of a collection type. It’s quite inconsistent.

createActionAllowedFields and updateActionAllowedFields from useContentManagerEditViewDataManager are both [undefined].

select.js:52 Uncaught TypeError: Cannot read properties of undefined (reading ‘split’)
at select.js:52
at Array.map ()
at select.js:50
at mountMemo (react-dom.development.js:15442)
at Object.useMemo (react-dom.development.js:15738)
at useMemo (react.development.js:1521)
at useSelect (select.js:39)
at connect.js:6
at renderWithHooks (react-dom.development.js:14803)
at mountIndeterminateComponent (react-dom.development.js:17482)

The above error occurred in one of your React components:
in Unknown (created by CollectionTypeFormWrapper)
in div (created by CollectionTypeFormWrapper)
in div (created by styled.div)
in styled.div (created by CollectionTypeFormWrapper)
in div (created by CollectionTypeFormWrapper)
in div (created by CollectionTypeFormWrapper)
in div (created by styled.div)
in styled.div (created by CollectionTypeFormWrapper)
in form (created by EditViewDataManagerProvider)
in EditViewDataManagerProvider (created by CollectionTypeFormWrapper)
in CollectionTypeFormWrapper
in CollectionTypeFormWrapper (created by EditView)
in EditView
in EditView (created by Permissions)
in Permissions
in Permissions (created by EditViewLayoutManager)
in EditViewLayoutManager (created by Context.Consumer)
in Route (created by CollectionTypeRecursivePath)
in Switch (created by CollectionTypeRecursivePath)
in ErrorBoundary (created by CollectionTypeRecursivePath)
in CollectionTypeRecursivePath (created by Context.Consumer)
in Route (created by Main)
in Switch (created by Main)
in Unknown (created by Main)
in Main (created by ConnectFunction)
in ConnectFunction (created by PluginDispatcher)
in ErrorBoundary (created by PluginDispatcher)
in div (created by PluginDispatcher)
in PluginDispatcher
in PluginDispatcher (created by Context.Consumer)
in Route (created by Admin)
in Switch (created by Admin)
in div (created by styled.div)
in styled.div (created by Admin)
in div (created by Admin)
in div (created by styled.div)
in styled.div (created by Admin)
in GlobalContextProvider (created by Admin)
in UserProvider (created by PermissionsManager)
in PermissionsManager (created by Admin)
in Admin (created by ConnectFunction)
in ConnectFunction (created by Context.Consumer)
in injectIntl(Connect(Admin)) (created by Context.Consumer)
in Route (created by PrivateRoute)
in PrivateRoute (created by App)
in Switch (created by App)
in div (created by styled.div)
in styled.div (created by App)
in QueryClientProvider (created by App)
in div (created by styled.div)
in styled.div (created by App)
in Unknown (created by Theme)
in Theme (created by App)
in App (created by ConnectFunction)
in ConnectFunction
in Router (created by BrowserRouter)
in BrowserRouter
in IntlProvider (created by LanguageProvider)
in LanguageProvider (created by ConnectFunction)
in ConnectFunction
in StrapiProvider
in Provider

React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary.

Has anyone managed to do this in v4?

Managed to figure this out, maybe this can help anyone else who needs it…

Generated a plugin using strapi generate, deleted the strapi-server.js related file and made as minimal changes use this:

// src/plugins/preview-link/admin/src/components/PreviewLink/index.js
import React from 'react';
import { useCMEditViewDataManager } from '@strapi/helper-plugin';
import Eye from '@strapi/icons/Eye';
import { LinkButton } from '@strapi/design-system/LinkButton';

const PreviewLink = () => {
  const {initialData} = useCMEditViewDataManager();

  if (!initialData.slug) {
    return null;
  }

  return (
    <LinkButton
      size="S"
      startIcon={<Eye/>}
      style={{width: '100%'}}
      href={`http://foo.bar?slug=${initialData.slug}`}
      variant="secondary"
    >
      Preview on MainSite
    </LinkButton>
  );
};

export default PreviewLink;
// src/plugins/preview-link/admin/src/index.js
import pluginPkg from '../../package.json';
import pluginId from './pluginId';
import Initializer from './components/Initializer';
import PreviewLink from './components/PreviewLink';

const name = pluginPkg.strapi.name;

export default {
  register(app) {
    app.registerPlugin({
      id: pluginId,
      initializer: Initializer,
      isReady: false,
      name,
    });
  },

  bootstrap(app) {
    app.injectContentManagerComponent('editView', 'right-links', {
      name: 'preview-link',
      Component: PreviewLink
    });
  }
};

Which gives you:

can you please provide the whole documentation and file structure for strapi version 4

What if I would like to have more than one similar buttons for purposes other than preview? Is it possible? If so, how?

Hi daniel,

Hope you are doing well!

I implemented the preview button for content manager in STRAPI admin as per your comment in the form.

The plugin works, but the preview button is not showing for the single types. Its only showing for the collection types. Below is my code.


Please see the screen shot of admin:


Do you have any solution?
It will be helpful, if you can advice me!


Best,
Nithin Jay