Sanity: [feature discussion] Default values & Document templates

Created on 24 Apr 2018  路  12Comments  路  Source: sanity-io/sanity

Right now there's not way to specify default values in sanity.
This creates situations where if you create a document in the studio, but don't interact with one of the fields of the documents, that field will be missing when querying.

One possible approach, discussed in the gitter channel seems to be using document templates, meaning a JSON that matches the document schema, that will act as the default document value.
This can be more helpful than implementing the default values in the schema itself because it separates the default values from the schema definitions, and gives the user the option to create multiple templates to choose from.

In regards to how to integrate it with sanity, I was thinking of it being a separate package (@sanity/templates), which will import all parts that implement a template. templates will specify their type, similar to how schema fields specify them. The package will run a check to see the template implements the schema. In the studio, the package will add an option to choose a template when creating a new document (either through a dropdown menu, or a modal or something else). It could also have an option to fill only empty fields to avoid overriding user input.

That's the general idea that's hovering in my brain.
Thoughts & suggestions welcome.

Feature Request Needs Discussion

Most helpful comment

We will actually have something for you very soon @bjornwang! Stay tuned.

All 12 comments

Thank you @dan-dr!

I think we all agree that we will need some way of specifying default values, and there has been some internal discussion about templates too (which I'm not entirely up to date on), so pinging @simen, @rexxars, @evenwestvang and @kristofferj for input.

IMO there's also a few tradeoffs involved with defaults that gets written to new documents and these tradeoffs should be considered in this discussion:

1. Defaults are lossy.

There's no way to tell the difference between a user entered value and a default value that has been applied.
A missing value holds a piece of information: _the user has not entered anything_. The moment you write a default value to a field that the user has not explicitly given a value, you loose this piece of information. Surprisingly often this piece of information turns out to be useful later on.

2. Defaults can change.

If you want to change a default value, you may want to re-apply this default to existing documents too. Since the previous default values have been applied to existing documents (and you have lost information about whether values are user entered or applied as defaults), there's no way to identify the documents where the value is _missing_ and apply the new default to them (so this is in part related to the above point).

3. Defaults are often application specific.

Depending on context, you may want to treat missing values differently. If you have already applied defaults at the datastore level, you loose the ability to use different defaults in different contexts.

To be clear: these are not arguments against providing support for defaults, but in many cases it may make more sense to apply defaults at query time or render time, e.g. using coalesce(...), or <div>{document.someAttr || 'Default value for attr'}</div>

Although I haven't yet worked with Sanity and am firing from the hip here, I strongly prefer the existing behaviour for exactly the reasons listed by @bjoerge.

I know this isn't what was proposed, but I don't see having a synced schema definition cause a replication of an actual default value into every single record in a data set as a viable option, particularly at a scale. If that were the case, adjusting a default value might necessitate the system patching millions of records, which would get quite out of hand when you make a typo, and then change your mind a few times on what the default should be. Even if it is possible, it certainly wouldn't feel "sane" to me!

Now that said, when you're referencing the data in a few places, for example a static build system as well as front-end runtime generated content, it isn't very DRY to set defaults via identical document.someAttr || 'default value' statements in multiple spots or codebases.

On a system level, (and factoring in some kind of sync of schema from local to the back end), a viable solution might be being able to set field defaults against schema and have that do two relatively simple things:

  1. Show the default visually for the field in the Content Studio
    (but not necessarily actually write it into the data)

    This would provide for what is likely to be a common requirement, where a field should (at least appear) to start with the default value primarily for the content author's benefit, to jog their memory or make it more obvious what the field will do (compared to a completely blank field), while still allowing them to edit the value

  2. Provide a means to access the defaults for a document type
    (either as its own query, or as part of the response of a normal query)

    This leaves the defaults flexible, without data patching and prevents the need to hardcode the defaults within code, let alone in multiple places.

    Most importantly it leaves the logic that handles "under what circumstances the defaults are used/merged" up to the application that is parsing and implementing the data.

    It prevents Sanity needing to implement any kind of default merge rules, which are likely to be application specific and will quickly become complex when attempting to factor in different developers use cases, for example an undefined vs ''... some people will want it to use the default when the value is '', but some people will treat the empty string as "this has been explicitly set to empty", and you might even want to do both on a case-by-case basis within the same application.

As far as I can tell, 2. can be implemented in a "poor mans" way already, by creating a "default document" in each set of documents, naming it as such for example _default, using the fields on that record to set the defaults, and then retrieving that specific record or skipping over it as necessary within other systems.

I suspect that if any default functionality were added that impacts the UI, as per 1., content authors would require some kind of reset functionality on any field that implements a default. Functionally all the reset would need to do would be to strip the attribute from that particular record, so the other default logic could take over.

Interesting points. I agree with all the points and that it may cause abuse which results in bad experiences.
Maybe an approach of supplying templates or some other mechanism in the sanity client when querying would be more application/use-case specific.

There is an another aspect, when you integrate dataset to third-party system where you do not have ability to specify default in template or query. We are facing this issue and it's hard to calibrate empty means default in third-party UI.

This is an interesting discussion and raised some things I'd not considered when naively hoping for a simple

{
  name: 'viewCount'
  title: 'View Count',
  type: 'number',
  defaultValue: 0,
  readOnly: true
}

kind of thing.

I note though that databases like Posgres allow for default values in their schema definitions, and as far as I am aware, if you change the default values in the schema then it does not retroactively apply those defaults to prior data. Unless you manually migrate the data then the previously set defaults stay as defaults. That seems quite a reasonable approach to me.

Still eager for this to happen.

Default values have huge benefits in terms of usability, time saved, and reduced number of errors, and should have been a part of Sanity already.

While I really appreciate Sanity taking data quality seriously, many of the considerations mentioned by @bjoerge are unimportant or minor edge cases in most projects. Also, as setting a default is optional, the original behaviour can be kept by those who need it for their projects.

My experience is that defaults are mostly needed for fields with a limited set of choices, such as boolean values or arrays of predefined values (think workflow states, for example). Discussing default values for string or text fields that could lead to a lot of duplication of long texts across documents just derails the discussion. This is not the core of the problem. Developers can of course build bad solutions with defaults, but I'd argue that's beside the point.

1. Lossy defaults
While this argument applies in some cases, I'd argue for the majority of cases it's not important. Also, the current behaviour comes at a cost, as developers defensively have to guard against missing fields. My experience is that a lot of CMS developers have a more optimistic coding style, and that the expectation is they will always get a field value. This leads to backlogs full of bugs caused by missing fields. Defaults would solve a lot of problems here.

2. Defaults can change
This might be overthinking the problem. Don't let the perfect be the enemy of the good. All we need is a default setting saving editors time. If a standard value that can later be changed across documents is needed, this could also be solved by creating a schema for it. Defaults don't need to solve this problem, IMHO.

3. Defaults are often application specific
As @bjoerge already points out, developers have full freedom to apply defaults at query or render time, so this could also be kept out of the equation.

All in all, as long as applying defaults are optional, developers already have the freedom they need to handle the three mentioned considerations.

I think even a simple, straight-forward mechanism for default specified directly in the schema would provide great benefit, and I'm hoping to see one soon. Templates could always be added later as a mechanism to set values at create-time, and could then also override the defaults specified in the schema.

We will actually have something for you very soon @bjornwang! Stay tuned.

Hurray!! Very good news indeed. :-)

any progress on this one? would be so handy to have default values

There is progress, and we're getting closer. And I'm pretty sure it will be worth the wait!

It's finally here: Initial value templates.

Read more: https://www.sanity.io/blog/initial-values-for-sanity-studio

Hi guys! Maybe I missed it in the docs, but how can I use another field from the current schema as initivalValue? Example use case:

export default {
  name: "article",
  type: "document",
  fields: [
    {
      name: "heading",
      type: "string",
      title: "H1",
      validation: Rule => Rule.required()
    },
    {
      // should have "heading" as initivalValue!
      name: "seoHeading",
      type: "string",
      title: "SEO Heading",
      validation: Rule => Rule.required()
    },
  ],
};
Was this page helpful?
0 / 5 - 0 ratings

Related issues

zanedev picture zanedev  路  4Comments

miracle2k picture miracle2k  路  3Comments

camjc picture camjc  路  4Comments

maxmoeschinger picture maxmoeschinger  路  5Comments

robinpyon picture robinpyon  路  4Comments