Explanation
I have recently been building wikis with tiddler-building forms. Everything makes sense to me there, except for handling of default values. There, my defaults seem to be repeated too often. I’m wondering if there are better patterns for handling them.
Sample Code
Here is a sample form, created just to demonstrate my concerns:
<div class="data-entry">
<label>First Name:</label>
<$edit-text tabindex=1 tiddler={{{ [[$:/temp/entry-form]] }}} field="first-name" /> <br/><br/>
<label>Last Name:</label>
<$edit-text tabindex=1 tiddler={{{ [[$:/temp/entry-form]] }}} field="last-name" /> <br/><br/>
<label>Date of Birth:</label>
<$edit-text type="date" tabindex=1 tiddler={{{ [[$:/temp/entry-form]] }}} field="dob"/> <br/><br/>
<label>Dwelling:</label>
<$edit-text tabindex=1 tiddler={{{ [[$:/temp/entry-form]] }}} field="dwelling" default={{lookups!!default-dwelling}} /> <br/><br/>
<label>Favorite Animal:</label>
<$select tiddler={{{ [[$:/temp/entry-form]] }}} field=animal tabindex=1 cancelPopups="yes" default="Panda">
<$list filter="[enlist{lookups!!animals}]" >
<option>{{!!title}}</option>
</$list>
</$select> <br/> <br/>
<label>The glass is:</label>
<$select tiddler={{{ [[$:/temp/entry-form]] }}} field="glass" tabindex=1 cancelPopups="yes" default="white" default="half-full">
<option>half-empty</option>
<option selected="selected">half-full</option>
</$select> <br/> <br/>
</div>
<$button tabindex=1 >
<$action-sendmessage
$message="tm-new-tiddler"
title= {{{ [[Person/]] [{$:/temp/entry-form!!first-name}] [[ ]] [{$:/temp/entry-form!!last-name}] +[join[]] }}}
tags= "Person"
first-name= {{$:/temp/entry-form!!first-name}}
last-name= {{$:/temp/entry-form!!last-name}}
full-name= {{{ [{$:/temp/entry-form!!first-name}] [[ ]] [{$:/temp/entry-form!!last-name}] +[join[]] }}}
animal={{{ [{$:/temp/entry-form!!animal}!match[]else[Panda]] }}}
glass={{{ [{$:/temp/entry-form!!glass}!match[]else[half-full]] }}}
dwelling={{{ [{$:/temp/entry-form!!dwelling}!match[]else{lookups!!default-dwelling}] }}}
/>
Create
</$button>
The related lookups
tiddler is simply:
title: lookups
animals: Alligator Butterfly Cow Dog Elephant Frog Goat Hippo ... Yak Zebra
default-dwelling: House
You can play with this form by downloading the following and dragging the resulting file to a wiki:
EntryForm.json (2.5 KB)
The Flow
Everything works reasonably well. (I’d always love feedback on how to do things better though!)
But…
The first three fields—first-name
, last-name
, and dob
—are simple enough; they don’t need default values. The user must enter them. At some point I’ll check out validation techniques to ensure they’re actually filled, but I don’t need it for my current work.
The next field—dwelling
— is a text entry field, with a default stored in a separate data tiddler. In one real wiki, the user will be almost always accept such a default value, but needs to be able to override it every once in a while. On rare occasions (yearly), the default value itself will need to change.
The next two—animal
and glass
—are <$select>
drop-downs; animal
gets it’s list of values from a filter (here simplified to a lookup in another tiddler), and glass
has just two hard-coded choices. Both have default values hard-coded in the <$select>
widgets.
All of this would be fine, but then in the ActionSendMessage
widget, I need to repeat these three default values.
The fields without defaults are simple enough:
first-name= {{$:/temp/entry-form!!first-name}}
or slightly more complex as I combine entry fields in title
and full-name
.
But for these ones with defaults, I cannot accept the value in my temporarily tiddler aligned with the associated field. That is, I cannot do this:
glass= {{$:/temp/entry-form!!glass}}
This is because if the user has not changed the input element, then no value would be assigned to the field in the new tiddler. So I have to check for an empty value, and assign my default value instead, which means something like this instead:
glass={{{ [{$:/temp/entry-form!!glass}!match[]else[half-full]] }}}
The Problem
Any sort of dual-maintenance bothers me. It seems extremely likely that the default values of Panda
and half-full
could easily get out of sync between the two places they’re used.
The Question
Are there better patterns for doing these? I know I could use the dwelling
pattern for the other two.
That would put the text itself in a single location, but it still leaves the default handling in both the input definition and the create tiddler action widget. I would love it if this was just in one place.
@EricShulman demonstrated a technique using an EventCatcher
. That is definitely an improvement, but it only works when the user interacts with the control: tabbing through it or clicking on and off it. That subverts user expectations.
Another idea I’ve considered is finding a way to assign the default values to the fields of my temporary tiddler—here $:/temp/entry-form
— when the entry form tiddler is rendered. That sounds like it would address most of these concerns. But I have no clue how to perform an action “when the tiddler is rendered”. Is this easy to do?
And in general, do you have other tools or techniques to solve this problem?