TOKEN_GROUPS renders chips under Customer / Project / Estimate / Other. Rows in the customer's submitted-details rail that map to a token are buttons: clicking 'Legal name: Jane Doe' inserts {{customer.legal_name}}. Insertion is caret-aware and adds spaces only where needed so tokens never fuse onto adjacent words.
Also called: insert merge field · token chips · click to insert placeholder
- 1insertAtCursor() reads selectionStart/selectionEnd, pads with a leading or trailing space when the neighbouring character isn't whitespace, and restores focus with the caret after the inserted text.
- 2Clicking a chip or a mapped detail row switches the pane to Edit first, then inserts.
- 3Rows without a mapped token (documents, secondary phone) render as plain, non-clickable detail.
- 4Hint text on both panes: 'Click a field or value to drop its placeholder into the contract — it fills in automatically for each customer.'
The rationale is written into the helper: 'In send-mode the row is clickable: clicking it drops the {{token}} into the contract body (so the builder inserts the placeholder, not the one-off literal).' Typing a customer's name as literal text into a body that will be re-rendered is exactly the mistake this prevents.
- Hard-coded literals where a merge field belongs
- Tokens fused onto neighbouring words and failing to render
- Merge-field syntax being a barrier to editing
See it on your own jobs
Twenty minutes, your numbers, no slide deck. We’ll build one of your real buildings in front of you and send you the estimate link at the end — yours to keep either way.
or keep browsing features →