Create a Clearable TextBox with the Dojo Toolkit

By  on  

4/18/2011: ClearTextBox has been updated to hide the clear icon when the value is empty. ClearTextBox has also been updated to use this.connect instead of dojo.connect for code efficiency reasons described by Chris Barber within the comments below.

Dojo Clear Box

Usability is a key feature when creating user interfaces;  it's all in the details.  I was recently using my iPhone and it dawned on my how awesome the "x" icon is in its input elements.  No holding the delete key down.  No pressing it a billion times.  No attempt  to highlight the text and then delete.  It's one tap.  Boom.  Text gone.  With that in mind, I took Dijit's dijit.form.TextBox and created my own widget which features a clear link.


We'll need to add some padding to the TextBox domNode to prevent text running behind the widget.  Then we'll use some absolute positioning to position the clear link to the right.  The border of the TextBox widget is on a wrapping DIV, not the INPUT element itself, so the link will appear inside the bordered box:

/* Define clear */
.claro .davidwalshClearBox { 
	padding-right: 25px; 
	position: relative; 
.claro .davidwalshClearBox a.davidwalshClear { 
	width: 12px;
	height: 12px;
	display: block;
	overflow: hidden;
	text-indent: -5000px;
	position: absolute;
	top: 4px; 
	right: 5px;
	background: url(closeButtonSprite.png) 0 0 no-repeat;
	z-index: 2000;
	cursor: pointer; 
.claro .davidwalshClearBox a.davidwalshClear:hover { 
	background-position:-12px 0; 
.dj_ie .claro .davidwalshClearBox a.davidwalshClear	{ 

Unfortunately there's a IE-specific hack to get the link vertically centered within the box.  Damn.

The Dojo JavaScript

My first attempt had me creating a custom template for the widget;  I copied dijit.form.TextBox's template and added the clear link within the HTML.  The problem with that was if dijit.form.TextBox's template changed, my widget template could be obsolete and troublesome because I inherit from other parts of TextBox.  I instead chose to inject a link and adjust sizing within the postCreate method:

// Provide our new class

// Request dependencies

// Declare our new class
// Declare our new class
dojo.declare("davidwalsh.form.ClearTextBox", dijit.form.TextBox,{

	// The "Delete" word
	deleteText: "Delete",
	// Fire the change event for every text change
	intermediateChanges: true,
	// PostCreate method
	// Fires *after* nodes are created, before rendered to screen
	postCreate: function() {
		// Do what the previous does with this method

		// Add widget class to the domNode
		var domNode = this.domNode;
		dojo.addClass(domNode, "davidwalshClearBox");

		// Create the "X" link
		this.clearLink = dojo.create("a", {
			className: "davidwalshClear",
			innerHTML: this.deleteText
		}, domNode, "first");

		// Fix the width
		var startWidth =, "width"),
			pad =,"paddingRight");, "width", (startWidth - pad) + "px");

		// Add click event to focus node
		this.connect(this.clearLink, "onclick", function(){
			// Clear the value
			this.set("value", "");
			// Focus on the node, not the link

		// Add intermediate change for self so that "X" hides when no value
		this.connect(this, "onChange", "checkValue");

		// Check value right away, hide link if necessary
	checkValue: function(value) {
		dojo[(value != "" && value != undefined ? "remove" : "add") + "Class"](this.clearLink, "dijitHidden");

As always, the first steps of creating a Dojo class are providing the new class and requiring its dependencies.  The next step is declaring the new class by providing the class name as the first argument, its dependencies as the second argument, and its properties in method in the third.  The postCreate method within a Dijit widget fires after all nodes in the template have been created but before the widget is rendered to the page.  So once I have the widget's wrapping domNode, I add the widget's special CSS class and create the "X" clear link.  With the link in place, I measure the domNode and subtract the padding we added with the CSS class so that the widget conforms to the width desired by the instance.  The last step is adding a click event to the node clears the INPUT's value and focuses on it.

Thanks to Dojo's powerful inheritance system, my custom class can remain small but lethally potent!  Try out the demo on your mobile phone -- it will work great!

Recent Features

  • By
    Camera and Video Control with HTML5

    Client-side APIs on mobile and desktop devices are quickly providing the same APIs.  Of course our mobile devices got access to some of these APIs first, but those APIs are slowly making their way to the desktop.  One of those APIs is the getUserMedia API...

  • By
    CSS Animations Between Media Queries

    CSS animations are right up there with sliced bread. CSS animations are efficient because they can be hardware accelerated, they require no JavaScript overhead, and they are composed of very little CSS code. Quite often we add CSS transforms to elements via CSS during...

Incredible Demos

  • By
    Drag and Drop MooTools File Uploads

    Honesty hour confession:  file uploading within the web browser sucks.  It just does.  Like the ugly SELECT element, the file input is almost unstylable and looks different on different platforms.  Add to those criticism the fact that we're all used to drag and drop operations...

  • By
    CSS calc

    CSS is a complete conundrum; we all appreciate CSS because of its simplicity but always yearn for the language to do just a bit more. CSS has evolved to accommodate placeholders, animations, and even click events. One problem we always thought...


  1. Well done! Dijit has come a long way allowing you to easily do things like this.

  2. valugi

    omg, complicated.

  3. Just noticed that you could change




    so that the onclick event is disconnected when the the widget is destroyed instead of page unload. It’s not a huge deal as long as you’re not created and destroy several of these textboxes in a single page view.

  4. Nathan Sweet

    Hey David, heads up. I’m using FF4 Beta right now, and for some reason I couldn’t scroll on your website, though I could still use the scroll bar to move up and down.

  5. cool… I like it..

  6. hi david
    for support rtl language,i edit your code,i should do anything else?

    add:.claro .davidwalshClearBoxRtl { padding-left:25px; padding-right:0px !important; }
    remove: right:5px; from .claro .davidwalshClearBox a.davidwalshClear 
    dojo.addClass(this.domNode,(this.isLeftToRight())?"davidwalshClearBox":"davidwalshClearBox davidwalshClearBoxRtl");
    add style:(this.isLeftToRight())?"right:5px":"left:5px" to dojo.create("a"
    edit:pad =,(this.isLeftToRight())?"paddingRight":"paddingLeft");
  7. Fantastic! MooTools version please!! ;o)

  8. Using this.connect has issues when you extend this widget.
    For example: this.connect(clearLink,”onclick”,this, “clearTextBoxValue”);

    When I try to connect to ‘clearTextBoxValue’ from child class:
    dojo.connect(this, “clearTextBoxValue”, this, “_doSomething”);
    _67.apply is not a function
    [Break On This Error] return _67.apply(_66,arguments||[]);

    Changing to dojo.connect(clearLink,”onclick”,this, “clearTextBoxValue”); – fixed the issue

    Btw, can I freely reuse this or is there any restriction? Thanks.

  9. This is really nice post, I have just started the dojo, this will be helpful, great stuff, keep it up..

  10. Nick Alther

    Has anyone successfully ported this to use

    • I’m not aware of anyone doing that, but it really shouldn’t be too hard. The CSS selectors need to be changed, and “dijit.form.TextBox” will need to be changed. That should be just about it.

  11. Nick Alther

    The problem I am encountering is the onChange event doesn’t fire on each keystroke because the intermediatechanges option isn’t available in since it uses dijit.form._FormValueMixin as opposed to _FormWidgetMixin.

  12. Great article!! I will try this widget out. Question – how do you get the blue hilited boarder when the text box receives focus? TIA. Steve

  13. Agupta

    Has any one tried the same implementation for ?

  14. I think i tried basically the same but iPhone virtual keyboard foiled my plans.
    I ended up by creating a wrapping div, which also solved layouting problems with 100% width in the end.
    You can contact me for my class if you are in need.

    Kind Regards
    gizmore from wechall

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!