Skip to main content
Ben Nadel at CFUNITED 2009 (Lansdowne, VA) with: George Murphy
Ben Nadel at CFUNITED 2009 (Lansdowne, VA) with: George Murphy

Utilities For Generating "id" / "for" Attributes In ColdFusion

By
Published in , Comments (1)

At PAI Industries, I've been working on a prototype for a new intranet application. This prototype contains many data entry forms. Normally, when I build forms, I hand-code the id attribute on inputs and the for attribute on the associated labels. But for the prototype, I've been using a utility method that constructs these values using a simple counter. And I kind of like it. It feels like one less piece of boilerplate that I have to think about.

The concept is simple. But I tried to flesh it out a bit in this ColdFusion exploration. I have two methods:

  • nextUid() - this increments a request-scoped counter (this approach isn't meant to be thread-safe) and returns the latest token.

  • getUid() - this reads the most recently created counter token, optionally providing a suffix (or list of suffixes) to use in the rendered attribute.

The goal is to make it easy to create matching pairs of id / for values; and, to add a tiny bit of magic for aria attributes. Here are my two method:

<cfscript>

	/**
	* I create a new uid token and return it.
	*/
	private string function nextUid() {

		// Ensure that the counter exists and is incremented on every call. This is
		// intended to be used within the context of a single request thread and is NOT
		// meant to be thread-safe or globally unique.
		request.$$uid = ( ( request.$$uid ?: 0 ) + 1 );

		return getUid();

	}

	/**
	* I get the most recently created uid token. If a space / comma delimited string is
	* passed-in, a compound token will be returned.
	*/
	private string function getUid( string after = "n" ) {

		return after
			.listToArray( ",; " )
			.map( ( suffix ) => "uid#request?.$$uid##trim( suffix )#" )
			.toList( " " )
		;

	}

</cfscript>

The nextUid() method increments the request.$$uid counter and returns the generated token (calling getUid() in its return statement). The getUid() method wraps the current counter in a prefix (uid) and an optional suffix. If you provide the suffix as a delimited list, the getUid() method will return a string containing separate outputs for each item in the list.

These methods aren't intuitive until you see how they get used. Here's a simple ColdFusion form with two text inputs followed by a textarea. Pay closer attention to the textarea field because it uses aria-describedby to reference both a description and a note for the field, each of which needs a unique id value.

<cfinclude template="./ids-core.cfm" />
<cfoutput>

	<p>
		<label for="#nextUid()#">
			Name:
		</label>
		<input id="#getUid()#" name="name" />
	</p>
	<p>
		<label for="#nextUid()#">
			Email:
		</label>
		<input id="#getUid()#" name="email" />
	</p>
	<p>
		<!---
			Note: the uid is generated ONCE for this field; but is then consumed FOUR
			times (with various suffix values for ARIA-related attributes).
		--->
		<label for="#nextUid()#">
			Bio:
		</label>
		<span id="#getUid( "desc" )#">
			This will show on your public page.
		</span>
		<textarea
			id="#getUid()#"
			aria-describedby="#getUid( "desc md" )#"
		></textarea>

		<span id="#getUid( "md" )#">
			Bio content supports limited Markdown syntax.
		</span>
	</p>

</cfoutput>

For the first two fields, the nextUid() and getUid() simply work hand-in-hand to make the labels clickable. But, the final textarea example gets more exciting. First, there's the call to nextUid() to increment the request-scoped counter; but then there's four calls to getUid() to read that counter:

  • getUid( "desc" )
  • getUid()
  • getUid( "desc md" )
  • getUid( "md" )

Each of these reads the same request.$$uid counter; but each outputs a slightly different attribute value:

As you can see in the last form entry, all four calls to getUid() start with uid3; but, each has a distinct suffix which allows the id attribute to remain unique for all four invocations. Even the aria-describedby attribute ends up including two distinct id references within the same value.

I'm going to add this to Big Sexy Poems to see how it feels in a real world application. But, I'm curious to know if anyone else is using a technique like this?

Want to use code from this post? Check out the license.

Reader Comments

16,115 Comments

Here's the commit of my changes on Big Sexy Poems: 8a45e6 . There were a few places I couldn't apply the change since the id values were being referenced outside the scope of the form field (via htmx triggers). But, over all, I think this will make copy-paste-driven development much easier since I won't have to rename id/for fields as I create new fields.

Post A Comment — I'd Love To Hear From You!

Post a Comment

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel
Managed hosting services provided by:
xByte Cloud Logo