Skip to main content

Bind data to a node

This page shows how a node's props get their values: the six value sources, and how to write a path to a field. You need it when a prop shows a field, a fixed value, a pinned entry, a query or data your app passes in.

The examples use the Blog project: the Blog post content type, the Post hero and Related posts Sections, and the entry AI 101.

Value sources​

A binding's type says where a prop's value comes from. Studio has six.

binding.typebinding.valueReads
template{ "path": … }A field of the connected entry
static_valueA string keyA fixed value stored in the composition's static_value
contentstack{ "uid", "_content_type_uid", "path" }A field of one pinned entry
contentstack_queries{ "queryUID", "path" }The results of a pinned query
repeater{ "repeaterUID", "path" }A field of the current item in a Repeater
component_propsA stringA key in the data your app passes to the component

The API doesn't validate a binding's type or value, so a wrong one saves without an error. For how to bind in the editor, see Data sources.

Static values​

A static_value binding's value is a key, not the text you want to show. Studio names each key <nodeUID>-<propName>, and the SDK accepts any string.

{ "type": "static_value", "value": "hero_title-text" }

The text lives in the composition's static_value field, an object of typed buckets such as text, plaintext, number, boolean and choice. Each bucket is a list of { key, value } items.

{
"text": [{ "key": "hero_title-text", "value": "The team blog" }],
"choice": [{ "key": "hero_title-Tag", "value": ["h1"] }]
}
  • The SDK merges every bucket into one map, so the bucket name doesn't change which key matches.
  • In the object and array buckets the value is a JSON string, and the SDK parses it.
  • A choice value is a list of strings. A single select prop receives the first item.
  • A new composition starts with an empty static_value object.
  • When a key has no match, the prop shows its own value, then the registered defaultValue, then an empty value for its type. The SDK logs no error and shows no warning.
  • When you save in Studio, it deletes static_value items whose key doesn't start with a node UID from the tree.
  • Inside a Section, the Section's own keys override the Template's keys of the same name.

Pinned entries and queries​

A contentstack or contentstack_queries binding reads from data_sources. The API takes data_sources as an array and stores it as a JSON string.

[
{
"uid": "contentstack",
"data": [{ "uid": "blt9f8e7d6c5b4a3210", "_content_type_uid": "author" }]
},
{
"uid": "contentstack_queries",
"data": [
{
"uid": "latest-posts",
"name": "Latest posts",
"spec": {
"contentType": "blog_post",
"sourceType": "content_type",
"query": {},
"params": { "limit": 3, "desc": "created_at" }
}
}
]
}
]
  • The SDK reads a pinned entry from dataSources.contentstack under the key <content type uid>:<entry uid>.
  • A query spec has four fields: contentType, sourceType, query and params. sourceType defaults to content_type, and Studio writes only that value.
  • In params, limit, skip, asc and desc map to the Delivery API. desc and asc take a field UID.
  • The SDK sends params.include as reference includes, but Studio removes include, only and except from the filters you type.
  • Studio sets a new query's uid to its name in lowercase with spaces changed to hyphens, and keeps it when you rename the query.
  • A contentstack_queries binding reads an object with entries and count, not a bare list. A Repeater over a query reads its items from path: {} or path: { "entries": {} }.
  • A query that isn't in data_sources never runs, so a binding to its queryUID shows the prop's default. The SDK skips a query whose spec has no contentType, with no error.
  • A failed query request returns { entries: [], count: 0 }, so the list is empty and no error shows.
  • A pinned entry the Delivery API doesn't return leaves its bindings on the prop's default.
  • SDK 2.0.0 runs Pinned Queries.

Component data​

A component_props binding reads the data prop of <StudioComponent />, not a prop named componentProps. Its value can be a dotted path, such as newsletter.subscribers.

  • The Component Data you type in Studio is stored as the data_sources item with the uid external_data.
  • Without a data prop, component_props reads external_data. When you pass data, the SDK ignores external_data for the Template, even if data is an empty object.
  • With neither, the binding shows the prop's default.
  • Inside a Section, the Section's own external_data fills the keys that the data you pass leaves out.

Which sources each kind of composition has​

SourceConnected TemplateFreeform TemplateSection
templateThe entry you pass as templateEntryUid, or else the entry the URL pattern resolves toNone. The binding shows the prop's defaultThe linked_schemas entry that matches the Template's content type, or the first entry
contentstack, contentstack_queriesIts ownIts ownDeclared on the Section, and travels with it into every Template that embeds it
static_value, component_propsYesYesYes

A Section's selected_field narrows its template scope to that field. A Section's own scoped data holds only the pinned entries and queries its data_sources declares. On a freeform Template, a placed Section can read a pinned entry or a query instead of a Template entry.

Bind one field to a prop​

A bindable prop is stored as { "type": "<prop value type>", "binding": { "type", "value" } }. For a field of the connected entry, the binding is a template source with a path.

{
"type": "plaintext",
"binding": { "type": "template", "value": { "path": { "title": {} } } }
}

In binding.value.path, each key is a field name. Its value is a nested path object, or {} at the end. The SDK reads only the first key at each level, so a second sibling key is ignored.

You wantpath
The Blog post title{ "title": {} }
The canonical field in the SEO group{ "seo": { "canonical": {} } }
The Author card global field's name{ "author_card": { "name": {} } }
The Author's title, through the reference field author{ "author": { "title": {} } }
The whole bound scope{}
  • path: {} reads the whole bound scope: the entry on a Template, the narrowed field in a Section, and the current item in a Repeater.
  • One key with dots, such as { "seo.canonical": {} }, resolves the same as nested keys. Studio writes a Template or pinned entry path as one dotted key, and starts a new nested key only after a reference field. It writes a query path and a Repeater item path as nested keys, one for each segment.
  • Studio writes an empty string key when you pick a reference field, as in { "author": { "": {} } }. It reads the same as { "author": {} }.
  • A numeric key reads that array position, as in { "entries": { "0": { "title": {} } } }. When Studio scopes a Section's data, a path that lands on an array without an index reads element 0.

What a prop shows for each field type​

  • A string or plaintext prop accepts text, number and boolean values. A plaintext prop bound to a rich text field gets the raw HTML string, with no conversion.

  • A string prop bound to a group with one key shows that key's value. Bound to a group with several keys, it shows this message.

    This content may not display correctly in this view. Please contact your development team to update the component so it can support this type of content.

  • To bind a whole group, global field or block, use an object prop. object and array props skip the one-key unwrap.

  • When an array prop gets a value that isn't a list, the SDK passes it through and warns in the console. When a scalar prop gets a value of the wrong type, the SDK swaps in the prop's fallback without a warning.

Next, see Repeaters and condition blocks to repeat a node for each item or show it only when a condition holds.

Report a problem with this page