When and Why to Use
Use this to collect structured responses across multiple attributes. Ideal for:
Marking multiple items on the same scale (e.g. product attributes)
Capturing matrix-style input efficiently
Comparing the same options across rows
Supports recoding, randomization, and media-based rows.
Portrait Experience
Each row is displayed as a vertical block with radio buttons or buttons, depending on
style
Rows scroll vertically
Specify option input appears below the corresponding row when selected
Landscape Experience
Grid is shown in tabular layout with rows as items and columns as options
Works well with keyboard/remote input
Hover/focus interaction highlights active cell
Configuration Options
Option | Type | Required | Default | Description |
|
| yes | - | The prompt shown to the user |
| `List[str | MediaItem]` | yes | - |
|
| yes | - | Label used in reporting and data schema |
|
| yes | - | Options available for each row |
|
| no |
| "radio" or "button" display style |
|
| no |
| Randomize row order |
|
| no |
| Randomize option order per row |
|
| no | - | Options that are never randomized |
|
| no | - | Adds an "Other" option to all rows |
|
| no | "Please specify" | Prompt for the specify input |
|
| no | - | Image shown above the question |
|
| no | - | Maps options to alternate values |
| `Callable[[Dict[str, str]], str | None]` | no | - |
|
| no | - | Field to use for labeling row images |
|
| no |
| Whether to show labels under row images |
|
| no | - | Pixel bounds for row images |
|
| no |
| Skip question if rows are empty |
|
| no | random | Default selections for test data |
|
| no | - | Used for token substitution and grouping in reporting |
Example Code
Basic usage:
s.grid_select_question( "Please rate the following aspects of the product", row_name="Product Aspect", rows=["Quality", "Price", "Service", "Delivery"], options=["Poor", "Fair", "Good", "Very Good", "Excellent"] )
With recodes:
s.grid_select_question( "Rate the following aspects of the experience", row_name="Attribute", rows=["Cleanliness", "Friendliness", "Wait Time"], options=["Poor", "Fair", "Good", "Excellent"], recodes={ "Poor": "1", "Fair": "2", "Good": "3", "Excellent": "4" } )
With custom validator:
s.grid_select_question( "Rate the following aspects of {brand} cars", row_name="Attribute", rows=["Design", "Comfort", "Technology"], options=["Poor", "Fair", "Good", "Excellent"], topic="Tesla", custom_validator=lambda d: "Please vary your responses" if len(set(d.values())) == 1 else None )
Notes
Set
style="button"
for a more compact tap-friendly interfaceUse
recodes
to make scale responses easier to analyzeThe
custom_validator
helps enforce variation or specific logicspecify_option
enables per-row free text for non-listed choices