#dynamic slug for getEntry
1 messages · Page 1 of 1 (latest)
Hi @silver obsidian. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
To use a dynamic parameter when calling getEntry(), you can pass the slug as the second argument. However, it's important to note that getEntry() expects the id of the entry, not necessarily the slug. In many cases, the id is derived from the file name or path.
Here's how you can use a dynamic parameter with getEntry():
---
const { slug } = Astro.params;
const post = await getEntry('blog', slug);
---
This approach is typically used in dynamic route pages, such as [slug].astro.
However, if you're using custom slugs that differ from the file names, you'll need to use getCollection() first to find the entry with the matching slug, and then use getEntry() to fetch the full entry. Here's an example:
---
import { getCollection, getEntry } from 'astro:content';
const { slug } = Astro.params;
// First, get all blog entries
const allPosts = await getCollection('blog');
// Find the entry with the matching slug
const postEntry = allPosts.find(post => post.slug === slug);
// If found, get the full entry
const post = postEntry ? await getEntry(postEntry) : null;
---
This method allows you to use custom slugs while still leveraging the getEntry() function.
For more information on using getEntry() and working with dynamic routes in Astro, you can refer to the Content Collections API Reference and the Generating Routes from Content guide.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@silver obsidian Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@agile marlin
Sounds good.
can you help adjust my function
export async function getAllAuthorsData(
authors: CollectionEntry<"blog">["data"]["authors"],
): Promise<CollectionEntry<"authors">[]> {
const authorsData = authors.map(async (author:any) => {
const authorData = await getEntry("authors", slug);
if (authorData === undefined) {
throw new Error(
`Author "${author.slug}" not found in "authors" collection.`,
);
}
return authorData;
});
// return a promise that is resolved when all promises in the array have been resolved
return Promise.all(authorsData);
}
Let me check the knowledge base for you again. One moment! :books:
Based on the information provided in the knowledge sources, I can help you adjust your function to correctly use getEntry(). Here's an updated version of your function:
import { getEntry, type CollectionEntry } from 'astro:content';
export async function getAllAuthorsData(
authors: CollectionEntry<"blog">["data"]["authors"]
): Promise<CollectionEntry<"authors">[]> {
const authorsData = authors.map(async (author) => {
const authorData = await getEntry("authors", author.id);
if (authorData === undefined) {
throw new Error(
`Author with id "${author.id}" not found in "authors" collection.`,
);
}
return authorData;
});
// return a promise that is resolved when all promises in the array have been resolved
return Promise.all(authorsData);
}
Here are the key changes and explanations:
-
We import
getEntryandCollectionEntryfrom 'astro:content' at the top of the file. -
In the
getEntry()call, we useauthor.idinstead ofslug. This is becausegetEntry()expects theidof the entry, not the slug. Theidis typically derived from the file name or path of the content entry Content Collections API Reference. -
We've removed the
:anytype annotation from theauthorparameter in themapfunction. TypeScript should be able to infer the correct type based on theauthorsparameter type. -
In the error message, we now refer to the
idinstead of theslug.
This function assumes that the authors array in your blog entries contains objects with an id property that corresponds to the id of entries in the "authors" collection. If your data structure is different, you might need to adjust accordingly.
Remember that getEntry() is used to fetch a single entry from a collection. If you need to query multiple entries or use more complex filtering, you might want to consider using getCollection() instead Querying Collections.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@silver obsidian Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@agile marlin It looks like my config isn't picking up files for my other collection. This is the config. ```import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';
const other = defineCollection({
loader: glob({ pattern: ['.mdx?', '!/**'], base: 'src/content' }),
schema: z.object({
title: z.string(),
accent: z.string(),
}),
});
const work = defineCollection({
loader: glob({ pattern: ['*.mdx?'], base: 'src/content/work' }),
schema: z.object({
title: z.string(),
date: z.date(),
accent: z.string(),
desc: z.string(),
project: z.string(),
roles: z.array(z.string()),
img: z.string()
}),
});
export const collections = { other, work };
Let me check the knowledge base for you again. One moment! :books:
Based on the configuration you've provided, it seems that the issue might be with the glob pattern for your other collection. Let's analyze the configuration and suggest a possible solution.
For the other collection, you're using the following loader:
loader: glob({ pattern: ['*.mdx?', '!*/**'], base: 'src/content' }),
This pattern is looking for .md or .mdx files directly in the src/content directory, but not in any subdirectories. The !*/** part of the pattern explicitly excludes all subdirectories.
However, there might be a couple of issues:
-
The
?in*.mdx?is making thexoptional, so it would match both.mdand.mdxfiles. If you want to match only.mdxfiles, you should remove the?. -
The base directory is set to
src/content, which means it's looking for files directly in this directory. Make sure your files are indeed located directly insrc/contentand not in a subdirectory.
To fix this, you could try adjusting the loader pattern like this:
const other = defineCollection({
loader: glob({ pattern: '*.mdx', base: 'src/content' }),
schema: z.object({
title: z.string(),
accent: z.string(),
}),
});
This will look for all .mdx files directly in the src/content directory.
If your files are actually in a subdirectory of src/content, you should adjust the base and pattern accordingly. For example, if they're in src/content/other, you could use:
loader: glob({ pattern: '*.mdx', base: 'src/content/other' }),
If you're still having issues after making these changes, you might want to double-check:
- That your files exist in the correct location.
- That your files have the correct extension (
.mdxin this case). - That your files contain the required frontmatter fields (title and accent).