# Content Controls Showcase
Exercises the docx `sdt` property surface — **structured document tags**, better
known as **content controls**: bounded regions Word treats as fillable form
fields. Three files work together:
- **content-controls.py** — builds the doc via the **officecli Python SDK**.
- **content-controls.sh** — the CLI twin (produces the shipped `.docx`).
- **content-controls.docx** — the generated document, a small employee-intake form.
- **content-controls.md** — this file.
## The `sdt` element
An `sdt` is added under `/body` (block-level, wrapping paragraphs) and reads
back at the stable path `/body/sdt[@sdtId=N]` (positional `/body/sdt[N]` also
works):
```bash
officecli add file.docx /body --type sdt --prop type=text --prop alias="Full Name"
officecli query file.docx sdt # list every control with its props
officecli get file.docx /body/sdt[1] # read one control's property bag
```
The control **type cannot be changed after creation**.
`text`/`richtext`/`dropdown`/`combobox`/`date`/`picture`/`group`/`checkbox` can
all be created at add-time. (`buildingBlockGallery`/`repeatingSection` still
require creating the control in Word first, then editing via the CLI.)
Built on the [`officecli-sdk`](../../sdk/python) (one resident, writes shipped
over the pipe); falls back to the in-repo SDK copy when the package isn't
pip-installed.
## Regenerate
```bash
cd examples/word
pip install officecli-sdk
python3 content-controls.py # or: bash content-controls.sh
# → content-controls.docx
```
## Control types demonstrated
| # | Type | Purpose | Type-specific props |
|---|---|---|---|
| 1 | `text` (plainText) | Single-line text field | `text=` initial/placeholder content |
| 2 | `dropdown` | Pick-one, typing disabled | `items=`, `dropDown.lastValue=` |
| 3 | `combobox` | Pick-one **or** free type | `items=` (`display\|value`), `comboBox.lastValue=` |
| 4 | `date` | Calendar picker | `format=`, `date.fullDate/calendar/lid/storeMappedDataAs=` |
| 5 | `picture` | Image-insert placeholder | — |
| 6 | `richtext` | Formatted multi-run field | `text=` |
| 7 | `group` | Locked grouping wrapper | — |
| 8 | `checkbox` | Check-box toggle (☒/☐) | `checked=` (`true`/`false`) |
## Shared props (every control type)
```bash
officecli add file.docx /body --type sdt --prop type=text \
--prop alias="Full Name" \ # human-readable label shown in Word
--prop tag=fullName \ # machine-readable data-binding key
--prop text="[Enter full legal name]" \ # initial / placeholder content
--prop lock=unlocked \ # unlocked | contentLocked | sdtLocked | sdtContentLocked
--prop placeholderText=DefaultPlaceholder # docPart gallery reference
```
`lock` semantics: `contentLocked` freezes the content (readback `editable=false`),
`sdtLocked` blocks deletion of the control, `sdtContentLocked` does both.
`placeholder=true` marks the control as currently *showing* its placeholder text
(``).
## Per-type props
### 2 + 3. dropDown / comboBox — choice lists
```bash
# dropDown: choices only, no free typing
officecli add file.docx /body --type sdt --prop type=dropdown \
--prop alias="Department" --prop tag=department \
--prop items="Sales,Engineering,Human Resources,Finance,Operations" \
--prop dropDown.lastValue=Engineering
# comboBox: same, but the user may also type a value not in the list.
# items= supports display|value form when the stored value differs from the label.
officecli add file.docx /body --type sdt --prop type=combobox \
--prop alias="Office Location" --prop tag=office \
--prop items="New York|NYC,London|LON,Singapore|SIN,Remote|REMOTE" \
--prop comboBox.lastValue=LON
```
`items=` is a comma list; each entry is either `display` or `display|value`.
`{dropDown,comboBox}.lastValue=` is the currently-selected stored value.
### 4. date — calendar picker
```bash
officecli add file.docx /body --type sdt --prop type=date \
--prop alias="Start Date" --prop tag=startDate \
--prop format="yyyy-MM-dd" \
--prop date.fullDate=2026-02-01T00:00:00Z \
--prop date.calendar=gregorian --prop date.lid=en-US \
--prop date.storeMappedDataAs=dateTime
```
`format=` is the display mask; `date.fullDate` is the actual selected value
(ISO-8601 UTC), distinct from the mask. `date.calendar` (e.g. `gregorian`,
`hijri`, `japan`), `date.lid` (locale id), and `date.storeMappedDataAs`
(`dateTime`/`date`/`text`) round out the picker.
### 5. picture — image placeholder
```bash
officecli add file.docx /body --type sdt --prop type=picture \
--prop alias="Profile Photo" --prop tag=photo
```
### 6. richText — formatted field
```bash
officecli add file.docx /body --type sdt --prop type=richtext \
--prop alias="Reviewer Notes" --prop tag=notes \
--prop text="Manager may add formatted commentary here." \
--prop lock=contentLocked
```
### 7. group — locked wrapper
```bash
officecli add file.docx /body --type sdt --prop type=group \
--prop alias="Approval Block" --prop tag=approval \
--prop text="Approved by HR — signature on file." \
--prop lock=sdtContentLocked
```
### 8. checkbox — check-box toggle
A real Word check-box content control. `checked=true` renders ☒ (2612),
`checked=false` renders ☐ (2610); the state is stored as a ``
marker in the control's `sdtPr`. `get` reads `type=checkbox` and `checked`.
```bash
officecli add file.docx /body --type sdt --prop type=checkbox \
--prop alias="Approved" --prop tag=hrApproved \
--prop checked=true
```
## Modifying after creation (`set`)
`alias`, `tag`, `lock`, and `text` are settable. The **per-type** props
(`dropDown.lastValue`, `comboBox.lastValue`, `items`, `format`, `date.*`,
`placeholderText`) are **add/get-only** — set at creation, read back on `get`,
but not modifiable via `set`.
```bash
officecli set file.docx /body/sdt[2] --prop alias="Home Department" --prop lock=sdtLocked
```
## Inspect
```bash
officecli query content-controls.docx sdt # one line per control
officecli get content-controls.docx /body/sdt[1]
```
```
/body/sdt[@sdtId=1] (sdt) "[Enter full legal name]" alias=Full Name tag=fullName lock=unlocked type=text editable=true placeholderText=DefaultPlaceholder
/body/sdt[@sdtId=2] (sdt) "" alias=Home Department tag=department lock=sdtLocked type=dropdown items=Sales,Engineering,Human Resources,Finance,Operations dropDown.lastValue=Engineering
/body/sdt[@sdtId=4] (sdt) "" alias=Start Date tag=startDate type=date format=yyyy-MM-dd date.fullDate=2026-02-01T00:00:00Z date.calendar=gregorian date.lid=en-US date.storeMappedDataAs=dateTime
/body/sdt[@sdtId=6] (sdt) "Manager may add formatted commentary here." alias=Reviewer Notes tag=notes lock=contentLocked type=richtext editable=false
```
Read-only readback keys: `id` (source of `@sdtId`) and `editable` (mirrors
`lock`). Full list: `officecli help docx sdt`.