Renderer for set field in backend

The set field is a nice feature, but the backend output is really ugly. I tried to build a renderer in this branch, but I don’t know all the fancy uikit class names, why I had to use evil inline CSS for testing purposes. I think, the idea is clear.

output before patch:

output after patch:

used options:

{
  "fields": [
    {
      "name": "test1",
      "type": "text",
      "label": "Super"
    },
    {
      "name": "test2",
      "type": "tags"
    }
  ]
}

Hey @raffaelj , sounds interesting but not sure if it’s the best approach for dealing with a set. For an end user, a set is just an aggregation of fields and probably viewing them in the collection table may not always result well, let’s imagine your set is composed of 10 fields!
For me, it should only display a name or description (we could define in the set options the field we want to retrieve the value), and maybe on mouse hover (or click) display a more complete representation of the values.

1 Like

@pauloamgomes I understand your concerns and I already added a check to display not more than 5 fields. It depends on the use case… I would assume, that a set of fields displays multiple fields. I have to think some more about the options to display fields. I’ll post an update in a few days.

Ok, but what happens if we have in the set a repeater or an asset/image?

What I was thinking was more having a display attribute that defines what we want to show from the set:

{
  "fields": [
    {
      "name": "title",
      "type": "text",
      "label": "Title"
    },
    {
      "name": "categories",
      "type": "tags"
    },
    {
      "name": "image",
      "type": "asset"
    }
  ],
  "display": ["fields[0].name"] 
}

we could also display many items:

"display": ["fields[0].name", "fields[2].image.path"]

And the value of display is used as reference to the entry values.

I would do it this way:

{
  "fields": [
    {
      "name": "title",
      "type": "text",
      "display": true
    }
  ]
}

The Screenshot above is from two sets and the first set is nested.

Set 1:

{
  "fields": [
    {
      "name": "title",
      "type": "text",
      "label": "Title",
      "display": true
    },
    {
      "name": "from",
      "type": "set",
      "display": true,
      "options": {
        "fields": [
          {
            "name": "date",
            "type": "date",
            "label": "Date",
            "display": true
          },
          {
            "name": "time",
            "type": "time",
            "label": "Time",
            "display": true
          }
        ]
      }
    },
    {
      "name": "to",
      "type": "set",
      "display": true,
      "options": {
        "fields": [
          {
            "name": "date",
            "type": "date",
            "label": "Date",
            "display": true
          },
          {
            "name": "time",
            "type": "time",
            "label": "Time",
            "display": true
          }
        ]
      }
    }
  ]
}

Set 2:

{
  "fields": [
    {
      "name": "test1",
      "type": "text",
      "label": "Super"
    },
    {
      "name": "test2",
      "type": "tags",
      "display": true
    },
    {
      "name": "test3",
      "type": "asset",
      "display": true
    }
  ]
}

PR: https://github.com/agentejo/cockpit/pull/909

I forgot a few things yesterday. Now it displays a simple items count if no field has "display":true and it works with custom sortable entries, too.

It doesn’t look perfect, but much better than the truncated json string.

2 Likes

That’s an amazing progress @raffaelj :ok_hand:

First of all thank you for the contribution and work you put into this.

I know that the rendering of the set field should be improved. But your provided solution has too many possible edge cases that may occur depending on all possible set configuration.

My idea was to introduce a display setting which will be used for the rendering.

e.g. "display": "{title} / {from} - {to}"

I hope you get the idea

Templating sounds good, too. But that could lead to the same problems if the wanted fields are repeaters or sets or if multiple fields have the same name. In my nested example I used “date” and “time” in both sets “from” and “to”.

The hardest things are the titles/labels inside the table layout. And maybe nested fields, where the parent has "display":false and a child has "display":true

Both would be possible - and it could overcomplicate things…

It’s Ok, if you don’t want it, but passing the field options to the renderer is really useful.

App.Utils.renderValue(renderer, content, field_definitions) or
App.Utils.renderValue(field, content) instead. I used the first option for backwards compatibility if someone already used custom renderers.

This way it would be easy to add an asset with custom Javascript and to overwrite original or to write missing renderers. So everyone could decide, if dates should be displayed localized, if a repeater should display some more than “3 Items” or how sets should look like etc.

Thanks for the update. Using a custom renderer with the new field definitions works like a charm. I added a mini tutorial how to use my renderer instead to my scripts collection.

I didn’t test your new renderer yet, but it looks like it only allows strings.

Hey @artur, do you plan to extend that to layout components inside the collection edit form, think would be a good idea, so instead of having only the component name we can have values from the component fields.

@pauloamgomes sorry, I didn’t get the question.

Resuming, as per above details, it would be possible to define what to display in the collection list for a set field, using an display setting to be used in the display.

Was thinking if same approach could be taken on the layout fields:

otherwise you can’t see what you have in the components and clicking on each one to see the values is not the best option

You can name each component in the layout, so it can give the editor a hint:

Or do you want some kind of preview?

1 Like

Well, that is a nice “easter egg”, was not aware of the possibility of give a name directly in the component content modal. That for sure helps. But still think that having the possibility to display more than the name can be helpfull. For example, if you an image or a set/repeater could be interesting to display a thumb of the image or some values from the set.

yes, I know what you mean. but there are so many possible edge-case, depending on the number of columns if using a grid etc that forces me to implement the most “balanced” solution.

But I’m always thinking about how to improve the layout field. So maybe there will be a better solution in the future :pray: