Mixins

Contents

Mixins are a smart way of dynamically extending existing content types with more fields.

The idea is to basically define new fields and decide what content types those fields should be applied to. If no content type is selected while registering a mixin, those fields will be enabled for all content types.

In Content Studio, a mixin is visually displayed as a separate section of the form, listed below the content type’s standard fields.

The tasks and examples in this chapter are based on work done in previous chapters (starting with the setup chapter). If you want to follow along with the examples, make sure you’re all caught up.

Your first mixin

If your requirement is to add new fields to a specific content type, it doesn’t make sense to use a mixin, since you can directly update that content type.

Now, if your requirement is to add new fields to multiple content types, that is when mixins come into place.

The same behaviour of extending multiple content types can be achieved through form fragments. You can create a form fragment and include it in the content types you want to extend. The difference is where the data in those fields is stored, and in the fact that mixins are easier to maintain when adding to a lot of content types - or to content types you don’t own, such as the built-in folders and media types.

When to use it

Use a mixin when the fields cut across content types rather than belong to one: SEO settings, editorial notes, tracking data. Mixins reach types you do not own, such as folders and media, can be made optional so editors switch them on per item, and keep their data apart from the type’s own fields under x. Use a form fragment when the fields are part of what the type is; they then land in data like any other field.

Let’s now add a "notes" mixin, which will extend both the Artist and Animal content types.

Similar to content types, mixin schemas have a specific naming and placement convention within your app: src/main/resources/cms/mixins/<mixin-name>/<mixin-name>.yaml.

  1. Create the "notes" mixin schema:

    src/main/resources/cms/mixins/notes/notes.yaml
    kind: "Mixin"
    title: "Notes"
    form:
      - type: "TextLine"
        name: "notes"
        label: "Notes"
        occurrences:
          min: 0
          max: 3
  2. A mixin schema on its own is dormant. You also need to register it, and define which content types it applies to. This is done in your app’s CMS descriptor, cms.yaml, which the starter created as an empty file:

kind: "CMS"
mixins:
  - name: "notes"
    allowContentTypes: "{app-name-full}:{content-type-1}|{app-name-full}:{content-type-2}" (1)

+ <1> A regular expression matched against the full content type name. Leave it out to apply the mixin to every content type in the project.

+ . Your app is redeployed, so open a Artist or an Animal content item. You should see the following section at the bottom of the form:

+ image::notes-x-data.png["Notes mixin fields showing at the bottom of an animal content item",width=1050]

+ . Finally, add some notes to some content.

For more details and configuration options for mixins, visit the mixins documentation and the CMS descriptor documentation.

Headless

As you might expect, your mixin fields are also available via the Guillotine API.

Mixin data is stored separately from the content type’s own fields, under the key x, grouped by the app that provides the mixin. Use the following query to quickly access all mixin fields in your content.

Querying for mixins
{
  guillotine {
    queryDsl(
      query: {
        boolean: {
          must: [
            {
              term: {
                field: "type",
                value: {
                  string: "com.example.tutorial101:animal"
                }
              }
            },
            {
              term: {
                field: "displayName",
                value: {
                  string: "Lynx"
                }
              }
            }
          ]
        }

      }
    ) {
      displayName
      xAsJson
    }
  }
}

If you’ve added any values to your Lynx’s Notes fields, this is what you might get.

Mixin results
{
  "data": {
    "guillotine": {
      "queryDsl": [
        {
          "displayName": "Lynx",
          "xAsJson": {
            "com_example_tutorial101": {
              "notes": {
                "notes": [
                  "Lynx note 1",
                  "Lynx note 2",
                  "Lynx note 3"
                ]
              }
            }
          }
        }
      ]
    }
  }
}

Should you require specific fields only, or wish to drill into more details, for instance by following a reference, use the typed GraphQL fields instead of xAsJson. For instance like this:

Typed mixin query
{
  guillotine {
    queryDsl(
      query: {
        boolean: {
          must: [
            {
              term: {
                field: "type",
                value: {
                  string: "com.example.tutorial101:animal"
                }
              }
            },
            {
              term: {
                field: "displayName",
                value: {
                  string: "Lynx"
                }
              }
            }
          ]
        }

      }
    ) {
      displayName
      x {
        com_example_tutorial101 { (1)
          notes { (2)
            notes (3)
          }
        }
      }
    }
  }
}
1 The app providing the mixin. Dots in the app name become underscores in GraphQL field names.
2 This is the name of the mixin. In this case, "notes" because we defined it to be like so in the notes.yaml file
3 This is the "notes" field (TextLine form item) inside the "notes" mixin.

If you made it here - you are officially equipped with an essential overview of Enonic’s fundamental content modelling capabilities. 🙌

Choosing the right tool

Your content model is complete, so here is everything you have used, side by side. Come back to this table when you model something new.

Tool Use it for Where the data ends up Sign you picked the wrong one

Content type

A kind of item editors create, find and publish on its own

An item with its own path, status and permissions

Items that are only ever edited together with one other item

Display name

The item’s own title

displayName on every item

A title field that always repeats it

Folder

Grouping items so paths stay meaningful

The path of every item beneath it

Paths nobody can predict

Reference (ContentSelector, ImageSelector)

Pointing at an item that exists on its own

The target’s ID; the item is reachable through the reference

Copying the same text or image into many items

Media

Files that are assets in their own right

A content item of a media type, with an attachment

Uploading the same file over and over

AttachmentUploader

Files that belong to one item

An attachment on that item

Wanting to link to the file from elsewhere

FieldSet

A tidier form

Nothing; the fields inside are stored as usual

Expecting it in the API

ItemSet

Repeating structured data the item owns

An object, or a list of objects, under data

Needing to publish or reuse the entries separately

OptionSet

A choice between variants with different fields

An object with _selected and one key per option

Every option is empty; use a ComboBox

Form fragment

The same fields in several schemas of your app

Exactly as if the fields were typed in place

Needing the fields on types you do not own

HtmlArea

Free-form prose

One HTML string, with links, images and macros resolved by the API

Parsing the HTML to find structure

Mixin

Fields that cut across content types, including built-in ones

Under x, grouped by app and mixin

The fields belong to one type only

Bonus: SEO Metafields

There’s a well-known app on Enonic Market named SEO Metafields. Its main purpose is to provide SEO capabilities to your project, and for that purpose, it adds a mixin, which is then enabled for all content types in your project.

This is a bonus section, so you’re not missing much if you skip it, but it’s worth installing it to better understand the capabilities of mixins.

  1. Install the SEO Metafields app from XP menu → Applications.

    Install SEO Metafields app
  2. Edit your project in Settings and add the app to it.

  3. Immediately after adding the app, the form of every content item gets a new section with the SEO fields.

    So, now you have some additional fields on all your content. If you check some of your content items, like an animal, you will see the fields are there as well.

SEO fields available for the animals content type as well.

Summary

Your content model is complete: content types, sets, references, rich text, media and mixins, all readable through the API.

Next up, let’s fetch it all from a front-end.


Contents

Contents