# Renderer for set field in backend

**URL:** <https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372>\
**Category:** Feature Request\
**Created:** [October 30, 2018, 8:32pm UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372 "2018-10-30T20:32:54Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![raffaelj](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/raffaelj/32/331_2.png) [@raffaelj](https://discourse.getcockpit.com/u/raffaelj)\
**Post date:** [October 30, 2018, 8:32pm UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372/1 "2018-10-30T20:32:54Z")

</div>

The set field is a nice feature, but the backend output is really ugly. I tried to build a renderer in [this branch](https://github.com/agentejo/cockpit/compare/next...raffaelj:improve-set-renderer), 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:

 ![cp-set-improve-test_before](https://canada1.discourse-cdn.com/flex030/uploads/getcockpit/original/1X/8cbbadede1cef75c3c6786d68e22ebb07fa46612.png)

output after patch:

 ![cp-set-improve-test](https://canada1.discourse-cdn.com/flex030/uploads/getcockpit/original/1X/2e383d98683e23bed0004b7d0203a9781aac7d99.png)

used options:

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

```

---

<div class="post-metadata">

**Author:** ![pauloamgomes](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/pauloamgomes/32/48_2.png) [@pauloamgomes](https://discourse.getcockpit.com/u/pauloamgomes)\
**Post date:** [October 31, 2018, 7:05pm UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372/2 "2018-10-31T19:05:13Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![raffaelj](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/raffaelj/32/331_2.png) [@raffaelj](https://discourse.getcockpit.com/u/raffaelj)\
**Post date:** [November 2, 2018, 5:46pm UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372/3 "2018-11-02T17:46:00Z")

</div>

@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.

---

<div class="post-metadata">

**Author:** ![pauloamgomes](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/pauloamgomes/32/48_2.png) [@pauloamgomes](https://discourse.getcockpit.com/u/pauloamgomes)\
**Post date:** [November 2, 2018, 7:43pm UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372/4 "2018-11-02T19:43:58Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![raffaelj](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/raffaelj/32/331_2.png) [@raffaelj](https://discourse.getcockpit.com/u/raffaelj)\
**Post date:** [November 5, 2018, 10:04pm UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372/5 "2018-11-05T22:04:34Z")

</div>

I would do it this way:

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

```

 ![cp-set-improve-3](https://canada1.discourse-cdn.com/flex030/uploads/getcockpit/original/1X/63dcbb89d02383201629c96825670070de5b2059.png)

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

Set 1:

```auto
{
  "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:

```auto
{
  "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](https://github.com/agentejo/cockpit/pull/909)

---

<div class="post-metadata">

**Author:** ![raffaelj](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/raffaelj/32/331_2.png) [@raffaelj](https://discourse.getcockpit.com/u/raffaelj)\
**Post date:** [November 6, 2018, 12:06pm UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372/6 "2018-11-06T12:06:50Z")

</div>

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.

 ![cp-set-with-items-count](https://canada1.discourse-cdn.com/flex030/uploads/getcockpit/original/1X/a07e24206ff6c9414f7d5605edb0787aade8d650.png)

 ![cp-set-sortable-with-item-count](https://canada1.discourse-cdn.com/flex030/uploads/getcockpit/original/1X/e55cf8304fffb688a6ae94ae5814015c3f22e385.png)

 ![cp-set-grid-view](https://canada1.discourse-cdn.com/flex030/uploads/getcockpit/original/1X/0f3ac0835f49ec6989b94a7f492c9007072daff9.png)

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

---

<div class="post-metadata">

**Author:** ![pauloamgomes](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/pauloamgomes/32/48_2.png) [@pauloamgomes](https://discourse.getcockpit.com/u/pauloamgomes)\
**Post date:** [November 6, 2018, 2:03pm UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372/7 "2018-11-06T14:03:27Z")

</div>

That’s an amazing progress @raffaelj 👌

---

<div class="post-metadata">

**Author:** ![artur](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/artur/32/4_2.png) [@artur](https://discourse.getcockpit.com/u/artur)\
**Post date:** [November 6, 2018, 9:55pm UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372/8 "2018-11-06T21:55:25Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![raffaelj](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/raffaelj/32/331_2.png) [@raffaelj](https://discourse.getcockpit.com/u/raffaelj)\
**Post date:** [November 6, 2018, 10:34pm UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372/9 "2018-11-06T22:34:58Z")

</div>

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”.

> [@artur](#):
>
> But your provided solution has too many possible edge cases

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.

---

<div class="post-metadata">

**Author:** ![artur](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/artur/32/4_2.png) [@artur](https://discourse.getcockpit.com/u/artur)\
**Post date:** [November 7, 2018, 8:00am UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372/10 "2018-11-07T08:00:25Z")

</div>

> <https://github.com/agentejo/cockpit/commit/907c1de5ba92f7bbab25635ad20d8b1d5d43a099>

---

<div class="post-metadata">

**Author:** ![raffaelj](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/raffaelj/32/331_2.png) [@raffaelj](https://discourse.getcockpit.com/u/raffaelj)\
**Post date:** [November 7, 2018, 10:58am UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372/11 "2018-11-07T10:58:07Z")

</div>

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](https://github.com/raffaelj/cockpit-scripts/blob/master/custom-renderers/README.md) to my scripts collection.

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

---

<div class="post-metadata">

**Author:** ![pauloamgomes](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/pauloamgomes/32/48_2.png) [@pauloamgomes](https://discourse.getcockpit.com/u/pauloamgomes)\
**Post date:** [November 7, 2018, 4:08pm UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372/12 "2018-11-07T16:08:49Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![artur](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/artur/32/4_2.png) [@artur](https://discourse.getcockpit.com/u/artur)\
**Post date:** [November 7, 2018, 4:54pm UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372/13 "2018-11-07T16:54:32Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![pauloamgomes](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/pauloamgomes/32/48_2.png) [@pauloamgomes](https://discourse.getcockpit.com/u/pauloamgomes)\
**Post date:** [November 7, 2018, 5:19pm UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372/14 "2018-11-07T17:19:01Z")

</div>

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:

 ![image](https://canada1.discourse-cdn.com/flex030/uploads/getcockpit/original/1X/b87c8f3b81504d53ed26afc18271457f89b49d7c.png)

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

---

<div class="post-metadata">

**Author:** ![artur](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/artur/32/4_2.png) [@artur](https://discourse.getcockpit.com/u/artur)\
**Post date:** [November 7, 2018, 5:32pm UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372/15 "2018-11-07T17:32:48Z")

</div>

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

 ![image](https://canada1.discourse-cdn.com/flex030/uploads/getcockpit/original/1X/80bd1e5af1865c99fe7d1dc47e8373997b7e4912.png)

Or do you want some kind of preview?

---

<div class="post-metadata">

**Author:** ![pauloamgomes](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/pauloamgomes/32/48_2.png) [@pauloamgomes](https://discourse.getcockpit.com/u/pauloamgomes)\
**Post date:** [November 7, 2018, 5:43pm UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372/16 "2018-11-07T17:43:39Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![artur](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.getcockpit.com/artur/32/4_2.png) [@artur](https://discourse.getcockpit.com/u/artur)\
**Post date:** [November 7, 2018, 9:22pm UTC](https://discourse.getcockpit.com/t/renderer-for-set-field-in-backend/372/17 "2018-11-07T21:22:34Z")

</div>

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 🙏
