-
-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Vue custom preview template #2183
Comments
I'd love to support Vue templates for previews 👍 👍 That issue you linked is a prerequisite to allowing any kind of template to be used, as it provides an API for parsing various template types. |
This comment has been minimized.
This comment has been minimized.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
This comment has been minimized.
This comment has been minimized.
2 similar comments
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Would be possible to do it by https://github.com/akxcv/vuera |
This comment has been minimized.
This comment has been minimized.
Has anyone tried to make it work with https://github.com/akxcv/vuera ? |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
1 similar comment
This comment has been minimized.
This comment has been minimized.
Hi all, please upvote the issue by clicking the upvote button 👍 . |
Hi guys, could anyone please provide a sample implementation using https://github.com/akxcv/vuera? |
Just tried to get this to work, but failed until now... Has anyone made progress on this? |
I have managed to get it to work with something as follows (inspired a bit by Vuera)
const MyTemplate = ({ entry, getAsset }) => {
const data = entry.getIn(["data"]).toJS();
let ref = React.createRef()
React.useEffect(() => {
vueWrapperRef(ref, data) // --> THIS IS THE IMPORTANT PART
},[data])
if (data) {
return <div ref={ref}></div>;
} else {
return <div>Loading...</div>;
}
};
export default MyTemplate;
let $vm
let DATA = {}
function vueWrapperRef(targetElement, data) {
if (!$vm){
DATA = data
$vm = new Vue({
el: targetElement.current,
render: function render(createElement) {
return createElement(MyVueComponent, { // --> MyVueComponent can be even an imported .vue file
props: DATA
});
},
})
} else {
Object.keys(data).forEach(key => {
DATA[key] = data[key]
})
$vm.$forceUpdate();
}
} |
@azriel46d uh, great news! Could you share a repository with a working example? That would be helpful! |
Ok, I got it working in a very basic way. I had to disable lots of things, since I am using nuxt. Some nuxt features that are broken for me:
Does anyone know how to render a nuxt app programmatically in the preview? This could be a starting point: https://nuxtjs.org/docs/internals-glossary/nuxt-render-route What we'd need to figure out is how we can pass data to the nuxt app. In nuxt 3 this might be quite easy: https://v3.nuxtjs.org/docs/usage/nuxt-app#nuxtapp-interface-advanced Another approach would be the nuxt preview mode could help: https://nuxtjs.org/docs/features/live-preview/ The advantage of this would be that the changes to the nuxt app would be minimal. But we'd need to provide nuxt with the data from the editor and that would be quite a challenge since we'd have to add that to the GET params, which isn't going to work for larger amounts of data. I am hijacking this issue here. Should I create a separate for nuxt previews? |
How I've solved it in the passed for ANY framework: In my netlify admin/index.html:
In my Vue preview page:
This setup can be used for any framework as the data is just being fetched from the parent of the iframe. Note: This worked in my time of using Netlify CMS, which might not be the same version currently. Hope it helps anyone! 👍 |
@mathieumagalhaes Thanks a lot for your suggestion! Ha, this is a very weird approach. Quite mind blowing that this actually works... But i love that the only thing needed is an iframe and that it doesn't matter what technology is being used in the preview. My nuxt app is showing the data for the editor in real time. I'll share code here once i am ready. I still need to clean up some things... |
Basic HTML and javascript, glad it helps |
@mathieumagalhaes great solution, thanks! |
So I'm working with Sveltekit and after a couple of tries I got this to work. I had to change a few things in your code to make it work with the newest version of Netlify CMS, though. First, the function import createClass from 'create-react-class'; Secondly, the function import React from 'react';
...
const element = React.createElement('div', { dangerouslySetInnerHTML: { __html: html } }); In Sveltekit I created a new page called Preview, where I import other pages as components and feed the window data into them: <script lang="ts">
import Homepage from '../+page.svelte';
import { browser } from '$app/environment';
let content: any;
if (browser) {
setInterval(() => {
content = window.parent.parent.previewDataCMS;
}, 1000);
}
</script>
<svelte:component this={Homepage} data={content} /> I also added a export const prerender = 'false' so that this page doesn't get prerendered. That's it! Thanks again! |
One more thing, to get all of the data available in the collection i replaced this part: const data = { type };
const keys = (properties || []);
if (Array.isArray(keys)) {
keys.forEach((key) => {
try {
const tmp = entry.getIn(['data', key]);
data[key] = tmp === 'undefined' ? '' : tmp;
} catch (e) {
console.log(e);
}
})
try {
data.mediaFiles = entry.get('mediaFiles')
} catch (e) {
console.log(e);
}
}
window.previewDataCMS = data; with: window.previewDataCMS = entry.get('data').toJSON(); |
@mathieumagalhaes Thank you so much for your comment here. You helped me save one of my projects, as the lack of live previews in our CMS was going to force our hand to change the stack. |
There is only one very important feature missing: Preview of new files that have not yet been saved. Does that work in the react preview? |
@letoast I remember looking for a helper function that did just that but couldn't found one back then. Great that it exists now.
@aminimalanimal My pleasure, I only hope Decap will actively maintain and start developing this project further.
@luksak That worked in my example, while editing (even for new files) the data refreshes thanks to the setTimeout. |
@mathieumagalhaes alright, I'm gonna test that. But I wonder how that would work. Is the data available as a blob? That would at least involve some custom code in a component rendering an Are you sure it works for you? |
@mathieumagalhaes I just researched this again. This is not working out of the box for sure. But there is I know this is far from clean code, but I'm just not familiar enough with React to solve this properly: import React from 'react';
const Preview = ({ entry, getAsset }) => {
function replaceAssets(data) {
Object.keys(data).forEach(key => {
if (key === 'src') {
data[key] = getAsset(data[key]).url
}
else if (typeof data[key] === 'object') {
data[key] = replaceAssets(data[key])
}
});
return data;
}
let src = '';
let host = window.location.host;
const localHostnames = ['localhost', '127.0.0.1', '0.0.0.0']
if (localHostnames.includes(window.location.hostname)) {
src = `http://${window.location.hostname}:3002/preview/`;
} else {
src = `https://${host}/`;
}
src += entry.toJS().slug
src += '?preview=true'
window.previewDataCMS = replaceAssets(entry.toJS().data);
const html = `<iframe border="0" src="${src}" width="100%" height="100%" style="border: 1px solid #EEE; height: calc(100vh - 80px)"></iframe>`;
return <div dangerouslySetInnerHTML={{ __html: html }} />;
};
export default Preview The |
_Could not find any issues that dealt with this, with the possible exception of #1041.
Is your feature request related to a problem? Please describe.
When developing a Vue project utilizing Netlify CMS I cannot import the Vue components as a custom preview template, as I can a React component.
Describe the solution you'd like
It would be nice to import (Gridsome) Vue template components and register them as custom preview templates.
Describe alternatives you've considered
The proposed Handlebars-like syntax mentioned in the issue above may be the closest thing we can get?
Additional context
N/A
The text was updated successfully, but these errors were encountered: