Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow item name/label to be passed to 'Add item' or 'Remove' buttons #4424

Open
1 task done
kuhlaid opened this issue Dec 18, 2024 · 2 comments
Open
1 task done

Allow item name/label to be passed to 'Add item' or 'Remove' buttons #4424

kuhlaid opened this issue Dec 18, 2024 · 2 comments
Labels
feature Is a feature request help wanted

Comments

@kuhlaid
Copy link

kuhlaid commented Dec 18, 2024

Prerequisites

What theme are you using?

bootstrap-4

Is your feature request related to a problem? Please describe.

I have a schema that looks like:

{
  "$schema": "http://json-schema.org/schema#",
  "title": "Dataset File Metadata - v1.0",
  "description": "This schema represents file metadata for a dataset.",
  "type": "object",
  "properties": {
    "files": {
      "title": "Files",
      "description": "Array of files contained within this dataset.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "title": "File name",
            "description": "**Must include file extension** (e.g. samplesTable.csv)",
            "type": "string"
          },
          "recordCount": {
            "title": "N value",
            "description": "Number of records found in the file.",
            "type": "integer"
          },
          "mimeType": {
            "title": "MIME type",
            "enum": [
              "application/pdf",
              "application/octet-stream",
              "image/jpeg",
              "text/css",
              "text/html",
              "text/javascript",
              "text/plain"
            ],
            "description": "A description of the file type used for HTTP requests.",
            "type": "string"
          },
          "directoryLabel": {
            "title": "Directory label",
            "description": "This a tag used in the organizing of the file within a repository; can be thought of as both a tag and file directory (e.g. 'data/reference').",
            "type": "string"
          },
          "dataDescription": {
            "title": "Data description",
            "description": "A description of the file purpose (e.g. A data table of all biological samples collected during clinic).",
            "type": "string"
          },
          "keywords": {
            "title": "Keywords",
            "description": "Used in tagging or keywords for finding the file within the dataset.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "internalReference": {
            "title": "Internal reference",
            "description": "References private (administrative) resources used by the file.",
            "type": "string"
          },
          "fileCount": {
            "title": "File count",
            "description": "If the file is an archive of many files, this field specifies the file count of the archive.",
            "type": "integer"
          },
          "fileSize": {
            "title": "Size of file (in bytes)",
            "description": "Specifies the file size.",
            "type": "integer"
          },
          "variables": {
            "title": "Variables",
            "description": "Provides the list of variables or columns in a data table and the details about each variable.",
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "title": "Variable name",
                  "description": "(e.g. SubjectId)",
                  "type": "string"
                },
                "label": {
                  "title": "A description of the variable.",
                  "description": "(e.g. Unique study participant identifying key)",
                  "type": "string"
                },
                "value": {
                  "title": "Value",
                  "description": "Properties of the variable value.",
                  "type": "object",
                  "properties": {
                    "format": {
                      "title": "Common statistical data types.",
                      "enum": [
                        "nominal",
                        "ordinal",
                        "interval",
                        "ratio",
                        "categorical",
                        "quantitative",
                        "discrete",
                        "continuous"
                      ],
                      "description": "(e.g. nominal, categorical, etc.)",
                      "type": "string"
                    },
                    "category": {
                      "title": "Category",
                      "description": "For categorical variables, this value lists the numeric values and their labels.",
                      "type": "object",
                      "patternProperties": {
                        "^.*$": {
                          "type": "string"
                        }
                      }
                    },
                    "dataType": {
                      "title": "Common data type",
                      "description": "(e.g. string, integer, character, etc.)",
                      "enum": [
                        "boolean",
                        "character",
                        "integer",
                        "float",
                        "string"
                      ],
                      "type": "string"
                    },
                    "unique": {
                      "title": "Unique values (yes/no)",
                      "enum": [
                        "Yes",
                        "No"
                      ],
                      "description": "Flag the values as unique for each record or not.",
                      "type": "string"
                    },
                    "unitOfMeasure": {
                      "title": "Unit of measure",
                      "description": "Specifies the value unit of measure where applicable (e.g. 'age in years').",
                      "type": "string"
                    }
                  },
                  "required": [
                    "format"
                  ]
                },
                "identifier": {
                  "title": "Identifier (yes/no)",
                  "enum": [
                    "Yes",
                    "No"
                  ],
                  "description": "Specify if the value is an identifying field for the data.",
                  "type": "string"
                },
                "ontology": {
                  "description": "Lists any applicable meta thesaurus entries related to the variable.",
                  "type": "object",
                  "properties": {
                    "source": {
                      "description": "URI of meta thesaurus entries",
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "source"
                  ]
                },
                "surveyQuestion": {
                  "title": "Survey question?",
                  "description": "If the value was derived from a survey question then this provides the question text.",
                  "type": "string"
                },
                "source": {
                  "title": "Variable source",
                  "description": "Specifies where the variable originates.",
                  "type": "string"
                }
              },
              "required": [
                "label",
                "name",
                "value"
              ]
            }
          }
        },
        "required": [
          "dataDescription",
          "directoryLabel",
          "name"
        ]
      }
    }
  },
  "required": [
    "files"
  ]
}

Using the bootstrap-4 theme as an example (using the https://rjsf-team.github.io/react-jsonschema-form/ playground), after I add a file, a 'Remove' button appears next to the Keywords field. This is simply a coincidence due to the schema layout, but makes it appear that the remove button is associated with the Keywords field (which it is not). The remove button, when hovered over simply says 'Remove' without any qualifier as to 'What' it is removing (see screenshot below).

I read through https://rjsf-team.github.io/react-jsonschema-form/docs/advanced-customization/internals/#custom-array-field-buttons and it seems that these labels are controlled by CSS, but the javascript themes seem to mostly reference <IconButton title={translateString(TranslatableString.RemoveButton)} which uses the enumerated constant TranslatableString to define the 'title' of the button.

image

Describe the solution you'd like

It would be helpful if the item label could be passed to the title of the 'Remove' button and 'Add' button. So in the case above where the Remove button is for the file, it would be nice if the Remove button title read something like 'Remove Files-0'. And instead of the Keywords 'Add' button having a title of 'Add item' it would read 'Add Keywords'.

I'm guessing the buttons could possibly read the 'label' from the widgets as mentioned in

- Updated `ArrayField`, `BooleanField`, `MultiSelectField` and `StringField` to pass `label` (read from `uiSchema.title` || `schema.title` || `name`) and `hideLabel` down to all of the `Widgets` they render, fixing [#827](https://github.com/rjsf-team/react-jsonschema-form/issues/827), [#2636](https://github.com/rjsf-team/react-jsonschema-form/issues/2636), [#2399](https://github.com/rjsf-team/react-jsonschema-form/issues/2399) and [#3531](https://github.com/rjsf-team/react-jsonschema-form/issues/3531)
in order to retrieve the item label, but I do not know if that is doable.

Describe alternatives you've considered

No response

@kuhlaid kuhlaid added feature Is a feature request needs triage Initial label given, to be assigned correct labels and assigned labels Dec 18, 2024
@kuhlaid kuhlaid changed the title Allow item name to be passed to 'Add item' or 'Remove' buttons Allow item name/label to be passed to 'Add item' or 'Remove' buttons Dec 18, 2024
@heath-freenome heath-freenome added help wanted and removed needs triage Initial label given, to be assigned correct labels and assigned labels Jan 17, 2025
@heath-freenome
Copy link
Member

@kuhlaid What you suggest is a good feature to have. If you are willing to do the work, here are most of the steps you would need to take for the implementation:

  1. Update the IconButtonProps to add a buttonName: string prop (this would be a breaking change, thus forcing the feature into the impending v6)
  2. Update the ArrayFieldTemplateItemType to add a itemName: string prop (this would be a breaking change, thus forcing the feature into the impending v6)
  3. Update the enums.ts file to add a %1 onto the CopyButton, MoveDownButton, MoveUpButton and RemoveButton values so that the name can be inserted
  4. Update the ArrayField.renderArrayFieldItem() method to add itemName: title to the returned object ArrayFieldTemplateItemType object
  5. Every theme would have to have its IconButton implementations updated to pass the buttonName as a second parameter to the translateString() call
  6. Every theme would have to update their ArrayFieldItemTemplate implementations to get the itemName prop from ArrayFieldTemplateItemType and pass it to the CopyButton, MoveDownButton, MoveUpButton and RemoveButton buttonName prop.
  7. Every theme would have to update their WrapIfAdditionalTemplate implementations to pass the keyLabel value as the buttonName for RemoveButton
  8. Update any necessary documentation in the packages/docs directory related to types and utility functions9. Add tests as necessary

That's alot, and if anyone would like to attempt this, feel free to ask any questions

@kuhlaid
Copy link
Author

kuhlaid commented Jan 18, 2025

Thank you @heath-freenome, your steps were very helpful. I began testing this solution. I added the implementation to the RemoveButton within the core as an example. I did not change the enums.ts file but instead opted for template literals within the IconButton title:

<IconButton
      title={`${translateString(TranslatableString.RemoveButton)} '${buttonName}'`}
...

I wrapped the buttonName in single quotes because it seemed weird without them. The result renders as the following using the core theme and the playground Arrays JSONSchema (I am hovering over the Remove button on the Additional item but the cursor does not appear in the screenshot):

Image

I believe something like this will work.

NOTE: While reviewing the solution I noticed that the additionalItems from the Arrays schema are missing the -1, -2... suffixes at the end of the field name when rendered in the form. These suffixes are useful when referencing the button titles, so I'm not sure if someone has posted this as a separate issue or not but it would be good to have these suffixes added to this use-case for consistency of array field rendering.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Is a feature request help wanted
Projects
None yet
Development

No branches or pull requests

2 participants