How to add a custom control/button for array items?

Hello,

I’d like to add a button to each entry of an array field. Let’s assume my data looks like:

"name": "Customer Order",
"payments": [
    {
      "status": "paid",
      "amount": 322
    },
    {
      "status": "unpaid",
      "amount": 100
    }
  ]

and json schema is:

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1
    },
    "payments": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "status": { "type": "string" },
          "amount": { "type": "number" }
        }
      }
    }
  },
  "required": ["name"]
}

I’d like to add an action button on each rendered item. Could you guide me on how to achieve that?

Btw. I managed to add a custom button on objects that are not array items. I did that by following your example with adding a field to schema.json (Custom Renderers - JSON Forms) and implementing a tester that would check on the existence of custom fields in the json schema:

export function buttonTesterFactory({rank=3, action=undefined}) {
  return rankWith(
    rank, //increase rank as needed
    schemaMatches((schema) => {
      return schema.form?.type === "button" && (action && action === schema.form?.action)
    }
  )
  )
}

and renderer:

  const {buttonLabel, onClick, isLoading} = props
  return (
    <Grid container>
      <Grid item xs={12}>
        <LoadingButton 
          sx={{marginBottom: '1rem'}}
          variant="contained"
          onClick={onClick}
          loading={isLoading}
        >
          {buttonLabel}
        </LoadingButton>
      </Grid>
    </Grid>
  );
};

but when trying to do the same for object being array item, it seems like the tester isn’t being matched. Is there a way to implement a tester to match objects being array items? (or maybe this can be achieved using uischema?)

Hi @Janekk,

we can render arrays in two different ways, either as a table or as a layout. In your case it will be rendered by default as a table because your items object is flat. You can force the array layout by setting the detail UI Schema option, see here. With that option you can just use your custom tester/renderer combo again.

If you like to render an additional button into the table, next to the existing buttons, you will have to create a custom table renderer. Alternatively, you could very hackily (like indicated with your custom tester?) add a third column by specifying another property for your items object and then just render a button instead of a property there. However I would not recommend that approach :wink: Note that when you want to customize the content of a table cell, you need to register a custom cell instead of a custom renderer. The concepts are the same, just the interfaces are a bit different.

Does this answer your question?

1 Like

Thanks @sdirix , using Ui schema with detail config helped! Will try using cell rendering