Hello, I am trying to make the last bits for my blog, and i am trying to get images in my posts so it's nicer.
However, I tried many ways and I cannot find a solution that would simply work.
Basically, my content-type Article looks like this in Astro for this version :
<header class="story__header -vertical">
<!-- article header -->
</header>
<section class="section">
<main class="main">
<article class="article">
<RichText richText={ content } />
</article>
</main>
</section>
My RichText Component, that I found in september in a blog article looks like this (isn't there a better way ?)
{
content.richText.map((node) =>
Text.isText(node) ? (
<Fragment>
<!-- some bits about bold and stuff -->
</Fragment>
) : (
<Fragment>
<!-- this is where i try to include images -->
{ node.type === "img" && (
<img
src={ escapeHTML(node.url) }
alt={ escapeHTML(node.children) } }
/>
)}
{!node.type && <p>{<Astro.self richText={ node.children } />}</p>}
</Fragment>
)
)
}
I know there is a way but i tried everything I could think about to get the images in articles. For now it's still Astro's templating system.
## The most important part:
My Payload response looks like this
{
"id": "6532b97610b7bdb6a1c7e6b9",
"title": "Test article",
"slug": "lorem-ipsum-dolor",
"categories": "Journal",
"tags": [
"Site web"
],
"article": [
{
"children": [
{
"text": "Oui juste un essai"
}
]
},
{
"children": [
{
"text": ""
}
],
"relationTo": "media",
"type": "upload",
"value": {
"id": "652b210331b92ebd6ad6f0be",
"alt": "Fenêtre de Powershell Windows qui liste toutes mes tentatives infructueuses pour créer un site web",
"filename": "ls-sur-terminal.png",
"mimeType": "image/png",
"filesize": 30414,
"width": 942,
"height": 480,
"createdAt": "2023-10-14T23:15:15.176Z",
"updatedAt": "2023-10-14T23:15:15.176Z",
"url": "/media/ls-sur-terminal.png"
}
},
{
"children": [
{
"text": ""
}
]
}
],
"_status": "published",
"createdAt": "2023-10-20T17:31:34.591Z",
"updatedAt": "2023-10-20T22:52:56.631Z"
}
You need to change your Astro template. Currently you're checking for
node.type === "img"
, which never happens. You need to check for
node.type === "upload"
and then adjust the template to get the URL and alt text in the correct way based on how the Payload response looks.
I get it, i tried that too but the whole file look like this, so it felt like it's based on HTML nodes :
Also yeah it gives a lot of errors and i hate it. I just need that part to work, and i'll refactor everything into react once that version is published
Yeah, unfortunately the default Slate typescript types are very barebones. You are supposed to define your own element types:
https://docs.slatejs.org/concepts/12-typescripteven in my front-end ?
{ node.type === "upload" && (
<img
src={ console.log(node) }
alt={ escapeHTML(node.alt) }
/>
)}
I am getting somewhere with this, i receive a
[Object object]
I guess i'll take a break and rewrite this in a more elegant way
After some thinking, what I don't understand in Slate docs and articles on the internet, it's the mention for the Editor. The Editor is in Payload, what I want to do is to render Elements in my Article. I don't need an Editor in Astro.
And find how to get the image from the API Response
For your src, you would use
node.value.url
Also, you are console logging inside your src, which is not helpful for you. You would want to console log outside of that
Yes, i tried everywhere 😭
i am trying this
mmh it returns undefined
I wish i could just see the structure in it
another code example to how to get the images i try to get from Slate
20:46:55 [astro] reload D:/Projets/Personnels/palingenae.be/2023/front-end/src/pages/blog/[slug].astro
[
{ children: [ [Object] ] },
{
children: [ [Object] ],
relationTo: 'media',
type: 'upload',
value: {
id: '652b210331b92ebd6ad6f0be',
alt: 'Fenêtre de Powershell Windows qui liste toutes mes tentatives infructueuses pour créer un site web',
filename: 'ls-sur-terminal.png',
mimeType: 'image/png',
filesize: 30414,
width: 942,
height: 480,
createdAt: '2023-10-14T23:15:15.176Z',
updatedAt: '2023-10-14T23:15:15.176Z',
url: '/media/ls-sur-terminal.png'
}
},
{ children: [ [Object] ] }
]
That's my
console.log(content)
in
[slug].astro
That's looking alright, there is an url here, you still have problems with the images?
Yes, whatever I do, it's either
undefined
or
[Object object]
. For the first i guess that the properties are not there. For the latter it feels like i have to go further, but Astro crashed because the value isn't right.
At this rate, i don't know what i forgot
Can you show where you are rendering an image
Here @jarrod_not_jared, I want to integrate those images with SlateJS
Node "upload", as of now
And here is where i want to call SlateJS RichText rendering
i fumble around to read the Media's URL
When your node.type is upload, it does not seem right that you are using node.element.path for the src
Wouldn’t it be what I said above?
node.value.url
?
i tried, it returns
undefined
And I think that the issue is that i copy pasted this
without understanding what it was about
but even after reading that code it does not makes sense, because it is supposed to work
and even if I go to upper layer,
article/[slug].astro
, i cannot get the image
So now my question, before going to sleep (i am GMT+2), what is the most common way to read images from nodes that come from SlateJS ?
Because I did read the documentation, and unless i couldn't wrap my head about something important, i didn't see what would help me render an image in my front-end
Looking at the data,
content
is an array, its second element is an object with a property type of value "upload". It also has a property value, and value.url looks like a valid url.
In
[slug].astro
if you write the following instead of using RichText:
{content.map((node) => <p>{node.type}</p>)}
I would expect the result on your webpage to be something like
undefined
upload
undefined
Now let's change the function a bit:
content.map((node) => {
if (node.type === "upload") {
return <p>{node.value.url}</p>
}
return <p>Not an upload node</p>
});
This time I would expect the result to be:
Not an upload node
/media/ls-sur-terminal.png
Not an upload node
If so, instead of returning the url in paragraph, try returning an img tag with its src set as the url:
content.map((node) => {
if (node.type === "upload") {
return <img src={node.type.url} />
}
return <p>Not a upload node</p>
});
It should display the image. If not, it means your web server is not set up to serve the
media
folder. But that's another story, let me know how these steps go first.
Thanks I’ll try this
I was so focused to make it work that i forgot it was an array
Thanks, i was tunnel visioned at the end
I have been near the solution well earlier
!solved
## My solution
{ node.type === "upload" && (
<img src={escapeHTML(`${import.meta.env.API_URL}${node.value.url}`)} alt={escapeHTML(node.value.alt)}/>
)}
So,
object.map()
was already occurring well higher, so i didn't need to do anything about it.
Another reason there was "
undefined
", it was because it needed an absolute path, the whole url to the image, the other simplest part I didn't think about.
Also, it motivates me to rewrite that
RichText
component because it's ugly and all red because of typing errors.
Thanks for your time @jarrod_not_jared, @dr_mint, @diesieben07
Glad it helped 👍
Star
Discord
online
Get dedicated engineering support directly from the Payload team.