Discussion about creating and rendering documents in Sanity Studio using the HTTP API and `S.documentList()`.
106 replies
Last updated: Apr 21, 2021
G
what does it mean?
AI Update
I'd love to help you understand something about Sanity, but your question "what does it mean?" doesn't specify what you're asking about.
Could you provide more context? For example, are you asking about:
- A specific error message you're seeing?
- A term or concept in the Sanity documentation (like "Content Lake", "GROQ", "perspectives", etc.)?
- A piece of code or configuration you're working with?
- A feature name you've encountered?
Once you provide more details about what you'd like explained, I'll be happy to give you a clear answer with relevant documentation and examples!
G
my code
export default () =>
S.list()
.title('Content')
.items([
S.listItem()
.title('Gestione Categorie')
.child(async () => {
const { data: categories } = await getCategories();
return categories?.map((element) =>
S.document()
.title(carTypes[element])
.documentId(`category-${element.toLowerCase()}`)
.schemaType('categoriesSettings')
);
}),
// Add a visual divider (optional)d
S.divider(),
// List out the rest of the document types, but filter out the config type
...S.documentTypeListItems().filter(
(listItem) => !['categoriesSettings'].includes(listItem.getId())
),
]);G
It looks like your
S.document()doesn’t have a
.schemaType()assigned.
G
but it’s wrong
G
user A
but it’s not true 😐G
sa you can see in the code
G
Yes, I see. Just trying to get the same thing going in my code.
G
this is my code
G
import S from '@sanity/desk-tool/structure-builder';
import carTypes from './static/categories';
import axios from 'axios';
import { IGetCategoryResponse } from '../server/src/controllers/getCategoriesController';
const http = axios.create({
baseURL: '<http://localhost:5000/api/v1>',
timeout: 1000,
});
function getCategories(): Promise<IGetCategoryResponse> {
return http.get('/cms/categories').then((res) => res.data);
}
export default () =>
S.list()
.title('Content')
.items([
S.listItem()
.title('Gestione pagina dei risultati')
.child(
S.list()
.title('Risultati per:')
.items([
S.listItem()
.title('Categoria')
.child(async () => {
const { data: categories } = await getCategories();
return categories?.map((element) =>
S.document()
.schemaType('categoriesSettings')
.title(carTypes[element])
.documentId(`category-${element}`)
);
}),
])
),
// Add a visual divider (optional)d
S.divider(),
// List out the rest of the document types, but filter out the config type
...S.documentTypeListItems().filter(
(listItem) => !['categoriesSettings'].includes(listItem.getId())
),
]);G
you can replace the categories with an array of strings
G
thanks for the help!
G
I will try in a couple of minutes, and I will let you know
G
This solution will render the document as listItem but I’m not able to edit the document.
G
morehover I’ve installed a plugin to order documents and I cant’ see that documents cause they are list item not a real documents
P
That's correct - you are pulling in these categories from outside the studio, so they are not actual documents until you create them. The above only sets them up in the desk structure so you can more easily create them with specific document IDs.
Regarding not being able to edit the documents, could you share your schema definitions for the
Regarding not being able to edit the documents, could you share your schema definitions for the
categoriesSettingsdocument type? Have you defined
__experimental_actionsby any chance?
P
That's correct - you are pulling in these categories from outside the studio, so they are not actual documents until you create them. The above only sets them up in the desk structure so you can more easily create them with specific document IDs.
Regarding not being able to edit the documents, could you share your schema definitions for the
Regarding not being able to edit the documents, could you share your schema definitions for the
categoriesSettingsdocument type? Have you defined
__experimental_actionsby any chance?
G
yep
G
__experimental_actions: [/*‘create’,*/ ‘update’, /*‘delete’,*/ ‘publish’],
G
is this the problem?
P
That's correct - you are pulling in these categories from outside the studio, so they are not actual documents until you create them. The above only sets them up in the desk structure so you can more easily create them with specific document IDs.
Regarding not being able to edit the documents, could you share your schema definitions for the
Regarding not being able to edit the documents, could you share your schema definitions for the
categoriesSettingsdocument type? Have you defined
__experimental_actionsby any chance?
P
Indeed, by commenting out "create" you are preventing the creation of these documents. What you could try if you do not want to allow additional
categoriesSettingsdocuments in the future, is temporarily uncommenting, then creating the docs by adding content to them, and commenting out
createonce more.
G
and If i will add more “categories” in the future on my api?
G
I have to remove the comment everytime?
G
why I can’t create directly the document instead of list item?
G
I read something about in the docs that was possibile
P
Then the same will apply, so you may want to consider taking a different route: either always allowing the creation of these documents or instead creating the documents using the HTTP API instead, which will ignore
__experimental_actions(it's just a studio concept).
P
For more information on creating docs using the HTTP API, see also: https://www.sanity.io/docs/http-mutations#c732f27330a4
G
G
By putting a string in this method, it will create a document with that ID if it doesn't already exist.
P
That's right: in the code above you are using this approach (
S.documentis in the
S.listItemchild) - when you start adding content to the empty documents, it will create a document with the provided ID. However, the creation process does rely on the
createaction being allowed for the document type.
P
That's right: in the code above you are using this approach (
S.documentis in the
S.listItemchild) - when you start adding content to the empty documents, it will create a document with the provided ID. However, the creation process does rely on the
createaction being allowed for the document type.
G
so the right approach is to create that documents
G
from the api
G
not in the studio
G
so if I have to render all the documents for that specific schemaType what I have to do?
P
If you want to disable document creation for a type in the studio and still create documents for it without temporarily adding
To render all documents available for a specific schema type, you can use a
createas an allowed action, then using the HTTP API is indeed a good alternative.
To render all documents available for a specific schema type, you can use a
documentListinstead. For example:
// deskStructure.js
...
S.listItem()
.title('Categories')
.child(
S.documentList()
.title('Categories')
.filter('_type == "categoriesSettings"')
),G
ok yes it work
G
ok yes it work
G
I have to facing the api now
P
Sorry about the confusion. There's plenty of stuff to get your head around at the beginning, but there are many advantages to being familiar with the HTTP API if you want to build advanced functionality later 🙂 Do let us know if you have any other questions.
G
Yeah i know,
G
I’m going to dig in to api docs
G
the token
G
the token
G
is going to expire?
G
I have to get it once?
P
If you use your user auth token (
sanity debug --secrets), it will indeed expire. However, you can set up robot tokens by opening your project on manage.sanity.io and going to Settings > API > Tokens > Add new token. These will not expire 🤖
G
ooooook
G
sorry one last question
G
<dataset-name>
G
is?
P
The name of your dataset (
productionby default). You can find all datasets on your project by going to your project on manage.sanity.io and opening the Datasets tab - or by using the
sanity dataset listcommand in your CLI (make sure to run it from your studio's root folder).
P
The name of your dataset (
productionby default). You can find all datasets on your project by going to manage.sanity.io > Settings > Datasets or using the
sanity dataset listcommand in your CLI (make sure to run it from your studio's root folder).
G
okok
G
export async function postNewCategories(categories: string[]): Promise<void> {
try {
await <http://http.post|http.post>('/data/mutate/production', {
mutations: categories.map((category: string) => ({
create: {
_id: category,
_type: 'categoriesSettings',
title: 'category',
},
})),
});
} catch (err) {
console.log(err);
throw new Error(err.message);
}
}G
so this should work
G
where http is an instance of axios with token and base url
G
I will le you know 😄
P
Yep, that looks alright to me as long as you can guarantee
categoryis unique enough for future usage as these document IDs have to be unique 🙂
G
yep those are unique cause I’ve already do a normalization my backend side
G
yep those are unique cause I’ve already do a normalization my backend side
G
it wokrs!!! ❤️
G
if it already exsist what happen?
P
Awesome! The operation will fail if a document with the provided ID already exists. If you prefer that it doesn't fail but skips existing ones, you can use
createIfNotExistsinstead of
create. If you wish to replace docs if they already exist, you can use
createOrReplace(not recommended here).
G
ok ok maybe createIfNotExists is perfect
G
S.documentList()
.title('Categories')
.filter('_type == "categoriesSettings"')G
In you experience is possibile to add a sort on this by specific field inside the document?
G
i mean, I’m using a plugin for ordering, and I would like to refect the ordering in the menu
G
when I use create from api I have to referecing the name of the schema right?
G
eg:
G
name: ‘resultBrandsSettings’, type: ‘document’,
title: ‘Brands’,
title: ‘Brands’,
G
resultBrandsSettings
P
That's correct: the
_type(mind the underscore) should be set to the schema type (
resultBrandsSettingsin this case)
P
That's correct: the
_type(mind the underscore) should be set to the schema type (
resultBrandsSettingsin this case)
G
it’s weird cause I’ve set it up all correct
G
the api works but results arent’ shown
G
what can I do to debug?
G
i’m trying in vision mode to quering
G
*[_type=="resultBrandsSettings"]
P
Are you able to query the documents? e.g.
sanity documents query '*[_type == "resultBrandsSettings"]'
P
Using Vision is fine too here
G
the array is empty
G
the function works, and the array with results is passed to the function
export async function postNewBrands(brands: IBrand[]): Promise<void> {
try {
await <http://http.post|http.post>('/data/mutate/production', {
mutations: brands.map((brand: IBrand) => ({
createIfNotExists: {
_id: brand.id,
_type: 'resultBrandsSettings',
title: brand.name,
},
})),
});
} catch (err) {
throw new Error(
`Sanity API Error: status:${err?.response?.status}, statusCode: ${err?.response?.statusText}`
);
}
}G
uhm
G
same for categories
G
P
Looks like only those docs are in your dataset right now: https://e83iap8s.api.sanity.io/v1/data/query/production?query=*
G
yeah
G
why?
G
on the Backend side i’ve changed just the name of the schema
G
nothing else
G
the weird part is if i change the method to create
G
i got conflicts
G
but as you can se here there’s any category inside https://e83iap8s.api.sanity.io/v1/data/query/production?query=*%5B_type%3D%3D%22resultCategoriesSettings%22%5D
G
categories [ 'cabrio-coupe', 'city-car', 'minivan', 'other', 'sedan', 'suv', 'van', 'wagon' ] Error: Sanity API Error: status:409, statusCode: Conflict
P
Have you double-checked your Axios instance uses the correct base URL (project ID and dataset name)?
P
That's correct though: those documents exist - just not under the document type. I'm suspecting it's an ID conflict as they share the same ID this way.
G
yes all correct in axios
G
oh ok
G
make sense
G
So i have to delete all before
P
Either that or adapt the IDs
G
let me delete
G
yep
G
fixed
G
yep
G
thanks buddy
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.