Relation widget - multiple collections

Hello, I’d like to reference a post in a collection using the relation widget, but the post could be in any one of three collections

I’m assuming this isn’t possible using the relation widget as it is now so…

  • Are there any solutions for this that people are using?
  • If not, is the easiest way to do this to just include three individual relation widgets?

Otherwise I’d be happy to spend some time on a custom widget to contribute to the community but… that ain’t happening in the next month or two!

2 Likes

Yeah, probably three widgets, although that sounds like a pretty rough UX. Can you explain the problem you’re solving at a higher level?

1 Like

Thanks for the response @erquhart!

What I’m trying to do is pretty simple - there will be a sticky post on the landing page which could come from any of three collections - let’s say blogs/reports/commentary

The problem now is that I’m about to be told that there will be more than three collections from which the sticky post will be drawn - so I might have to figure out something a bit more scalable. I can live with the rough UX for three collections, but not more, I think!

Ultimately, the ideal would be to have a relation widget which searches across ALL collections - is this even possible, do you think?

@rub1e A relation widget that could pull from multiple collections would be amazing. Please post back here if you end up making one eventually!

Searching multiple collections in a relation widget would be a cool feature. There are a few other feature requests that could provide what you need, such as conditional fields, but no really great way to do it currently.

I’ll give you the best approach I can think of, but first the drawbacks:

  • Nothing will be shown for this field in the preview pane
  • Each collection that you want to search will have to be indicated in the field config (won’t automatically work for all collections - but I can’t imagine a future solution that wouldn’t require this)
  • You only need one value, but this approach will use a list, so you’d only use the first value in the list
  • Uses a beta feature, so the API might change

Here’s how it would work:

  1. Use the beta list types feature
  2. For each collection that you want to query, add a type whose fields consist of a relation widget

Users could then select the collection they want to query by selecting the “type” of list item they want to add, then query away. Besides the caveats mentioned above, I’m pretty sure this will work. If you try it let me know how it goes.

1 Like

Can you give an example schema showcasing this use case? For examples, I am developing restaurant site and want to sketch out a scheme so that the menu can be generated. Each menu would have an arbitrary number of sections (Salads, Appetizer, Entree) with an arbitrary number of items (from two collections: drinks, dishes). Here is what I have so far but it doesn’t work (please forgive the indentation, the copy paste didn’t work):

collections:
  - name: menus
    label: Menu
    folder: "src/content/menus"
    create: true
    slug: "{{slug}}"
    fields:
      - { label: Name, name: name, widget: string }
      - { label: Description, name: description, widget: text, required: false }
      - {
           label: Hours,
           name: hours,
           widget: list,
           fields:
             [
               {
                  label: From,
                  name: from,
                  widget: datetime,
                  dateFormat: false,
                  format: "HH:MM",
               },
               {
                 label: To,
                 name: to,
                 widget: datetime,
                 dateFormat: false,
                 format: "HH:MM",
              },
           ],
        required: false,
      }
   - {
      label: Sections,
      name: sections,
      widget: list,
      fields:
        [
          { label: Section, name: section, widget: string },
          {
            label: "Food Items",
            name: fooditem,
            widget: list,
            types:
              [
                {
                  label: Dishes,
                  name: dishes,
                  widget: relation,
                  collection: dish,
                  valueField: name,
                  searchFields: ["name"],
                  multiple: true,
                  required: false,
                },
                {
                  label: Drinks,
                  name: drinks,
                  widget: relation,
                  collection: drink,
                  valueField: name,
                  searchFields: ["name"],
                  multiple: true,
                  required: false,
                },
              ],
          },
        ],
    }

  - name: side
label: "Side Dish"
folder: "src/content/sides"
create: true 
slug: "{{slug}}"
widget: list,
fields:
  [
    { label: Name, name: name, widget: string, required: true },
    {
      label: Description,
      name: description,
      widget: text,
      required: false,
    },
    { label: Price, name: price, widget: number, required: false },
  ]

  - name: dish
label: Dish
folder: "src/content/dishes"
create: true 
slug: "{{slug}}"
widget: list,
fields:
  [
    { label: Name, name: name, widget: string, required: true },
    { label: Description, name: description, widget: text },
    { label: Price, name: price, widget: number },
    {
      label: Sides,
      name: sidedishes,
      widget: relation,
      collection: side,
      valueField: name,
      searchFields: ["name"],
      multiple: true,
      required: false,
    },
  ]

  - name: drink
label: Drink
folder: "src/content/drinks"
create: true 
slug: "{{slug}}"
widget: list,
fields:
  [
    { label: Name, name: name, widget: string, required: true },
    {
      label: Description,
      name: description,
      widget: text,
      required: false,
    },
    { label: Price, name: price, widget: number },
    { label: Type, name: type, widget: select, options: ["white wine", "red wine", "rose wine", "cocktail", "beer", "non-alcoholic"] }
  ]

Hi @CaninoDev and welcome to the community.
Sorry for the late reply.

types under list widgets should be object widgets:
https://www.netlifycms.org/docs/beta-features/#list-widget-variable-types

Also, you can use a wildcard * to reference lists.

Can you please try the following:

collections:
  - name: menus
    label: Menu
    folder: 'src/content/menus'
    create: true
    slug: '{{slug}}'
    fields:
      - { label: Name, name: name, widget: string }
      - { label: Description, name: description, widget: text, required: false }
      - {
          label: Hours,
          name: hours,
          widget: list,
          fields:
            [
              {
                label: From,
                name: from,
                widget: datetime,
                dateFormat: false,
                format: 'HH:MM',
              },
              {
                label: To,
                name: to,
                widget: datetime,
                dateFormat: false,
                format: 'HH:MM',
              },
            ],
          required: false,
        }
      - {
          label: Sections,
          name: sections,
          widget: list,
          fields:
            [
              { label: Section, name: section, widget: string },
              {
                label: 'Food Items',
                name: fooditem,
                widget: list,
                types:
                  [
                    {
                      label: Dishes,
                      name: dishes,
                      widget: object,
                      fields:
                        [
                          {
                            label: Dishes,
                            name: items,
                            widget: relation,
                            collection: menu_items,
                            file: dishes,
                            valueField: dishes.*.name,
                            displayFields: [dishes.*.name],
                            searchFields: [dishes.*.name],
                            multiple: true,
                            required: false,
                          },
                        ],
                    },
                    {
                      label: Drinks,
                      name: drinks,
                      widget: object,
                      fields:
                        [
                          {
                            label: Drinks,
                            name: items,
                            widget: relation,
                            collection: menu_items,
                            file: drinks,
                            valueField: drinks.*.name,
                            displayFields: [drinks.*.name],
                            searchFields: [drinks.*.name],
                            multiple: true,
                            required: false,
                          },
                        ],
                    },
                  ],
              },
            ],
        }

  - name: menu_items
    label: Menu Items
    files:
      - label: Sides
        name: sides
        file: 'src/content/sides.json'
        format: json
        fields:
          - name: sides
            widget: list
            fields:
              [
                { label: Name, name: name, widget: string, required: true },
                {
                  label: Description,
                  name: description,
                  widget: text,
                  required: false,
                },
                { label: Price, name: price, widget: number, required: false },
              ]

      - label: Dishes
        name: dishes
        file: 'src/content/dishes.json'
        format: json
        fields:
          - name: dishes
            widget: list
            fields:
              [
                { label: Name, name: name, widget: string, required: true },
                { label: Description, name: description, widget: text },
                { label: Price, name: price, widget: number },
                {
                  label: Sides,
                  name: sides,
                  widget: relation,
                  collection: menu_items,
                  file: 'sides',
                  valueField: sides.*.name,
                  displayFields: [sides.*.name],
                  searchFields: [sides.*.name],
                  multiple: true,
                  required: false,
                },
              ]

      - label: Drinks
        name: drinks
        file: 'src/content/drinks.json'
        format: json
        widget: list
        fields:
          - name: drinks
            widget: list
            fields:
              [
                { label: Name, name: name, widget: string, required: true },
                {
                  label: Description,
                  name: description,
                  widget: text,
                  required: false,
                },
                { label: Price, name: price, widget: number },
                {
                  label: Type,
                  name: type,
                  widget: select,
                  options:
                    [
                      'white wine',
                      'red wine',
                      'rose wine',
                      'cocktail',
                      'beer',
                      'non-alcoholic',
                    ],
                },
              ]