- The Book of Dojo
- Quick Installation
- Hello World
- Debugging Tutorial
- Introduction
- Part 1: Life With Dojo
- Part 2: Dijit
- Part 3: JavaScript With Dojo and Dijit
- Part 4: Testing, Tuning and Debugging
- Part 5: DojoX
- The Dojo Book, 0.4
Creating a Widget Programmatically
Submitted by OpenBip on Tue, 06/05/2007 - 17:57.
This Document is Out of Date. For the current documentation, please see http://docs.dojocampus.org/
In Part 2: Dijit, you saw how to instantiate (create an instance of) a dojo widget declaratively, using the "dojoType" attribute:
<div dojoType="dijit.TitlePane" title="Outer Pane">
This is a title pane containing another title pane
<div dojoType="dijit.TitlePane" title="Inner Pane">
And this is the inner title pane...
</div>
</div>
This is a title pane containing another title pane
<div dojoType="dijit.TitlePane" title="Inner Pane">
And this is the inner title pane...
</div>
</div>
While this method is very convenient, widgets declared in this way are instantiated only when the page first loads. What if, however, you want to create a widget at some later time, e.g. as the result of a user-action? This is one case where we would want to instantiate a widget programmatically, which looks like:
var button1 = new dijit.form.Button(params, srcNodeRef);
Let's pick that programmatic example apart:
- var button1
- This is the name of the variable that will refer to the instantiated widget. You can use this variable to interact with the widget later (see Interacting With Widgets)
- dijit.form.Button
- This is the fully-qualified name of the widget you want to instantiate;
freeing you to, perhaps, later instantiate
yourmodule.form.Button(see Writing Your Own Widget Class) - params
- An object whose properties map to the widget's properties. Dijit uses this object to initializes the widget's properties. Thus, if the "params" object in this case has a "label" property, dijit will set the dijit.form.Button's "label" attribute to the value of that property. See Setting Properties below for elaboration.
- srcNodeRef
- This is either a reference to an existing DOM node, or the id of an existing DOM node. When the widget is successfully instantiated, this node will be replaced with the widget's node. New in 1.0: You can skip this parameter for dijit.Tooltip, dijit.TooltipDialog and dijit.Dialog. Since they require no specific place on the page, there's no sense in providing one.
Thus, the programmatic equivalent of:
from the example above would be:var innerPane = new dijit.TitlePane( {title:"Inner Pane"}, dojo.byId("someDiv"));
When that line executes, the div with the id "someDiv"
will be replaced with a TitlePane widget, with title "Inner Pane".
Setting Properties
Programmatically creating widgets allows extra freedom in the parameters. The following is perfectly legal:
var innerPane2 =
new dijit.TitlePane({
title: 'Creating New '+docType,
duration: 5 * 1000 /* 5 seconds, converted to ms */
}, dojo.byId("someDiv"));
In declarative widgets, you may only pass strings. In programmatic ones, you can pass arrays, nested objects, Dates or Numbers as parameters. This isn't important for bundled Dijit components - they all work with strings - but it can make building your own widgets easier.
New in 1.0: When programmatically creating a widget class, style, and id now need to be specified as parameters to the constructor, not as attributes of the placeholder node. For example, the following is incorrect:
<script>
// Doesn't work in 1.0. Class and style will be overwritten
new dijit.form.Button({},,dojo.byId("someDiv"));
</script>
<div id="someDiv" class="large" style="color:red"></div>
// Doesn't work in 1.0. Class and style will be overwritten
new dijit.form.Button({},,dojo.byId("someDiv"));
</script>
<div id="someDiv" class="large" style="color:red"></div>
The correct code:
// Works in 1.0
new dijit.form.Button({ "class": "large", style: "color: red" }, dojo.byId("someDiv"));
startup()
Certain widgets require a startup() method to be called. When building widgets programmatically, you create the parent first, then add the children, and grandchildren... and finally call startup(). Startup() is called once on the top element in the hierarchy, after the whole hierarchy has been setup and the element inserted.
It's good practice to include the startup() call, even for widgets that have no children or do not require it.
accordion = new dijit.layout.AccordionContainer({}, dojo.byId("accordionShell"));
accordion.addChild(new dijit.layout.ContentPane());
accordion.addChild(new dijit.layout.ContentPane());
accordion.addChild(new dijit.layout.ContentPane());
accordion.startup();
accordion.addChild(new dijit.layout.ContentPane());
accordion.addChild(new dijit.layout.ContentPane());
accordion.addChild(new dijit.layout.ContentPane());
accordion.startup();
- Printer-friendly version
- Login or register to post comments
- Unsubscribe post

Programmatic creation with IE6
A suggestion I got in the forums about this: IE is sensitive to adding stuff to the DOM while pages are loading.
It's better to put all the widget-adding code inside a dojo.addOnLoad() call, in order to have the browser finish
loading first.
Attaching to the Page - Dojo 0.9
In Dojo 0.9, the "sourceNodeRef" argument is a quick way to insert a widget into your page when instanciating programmitically. However, the drawback to this argument is that you must have a DOM node in mind, ready to be replaced as the "sourceNodeRef". What happens when you don't/can't have an expendable DOM node? Simple, create one on-the-fly and appendChild to your document. Next, supply this "placeHolder" node as the "sourceNodeRef" in your Dijit constructor.
Example:
var placeHolder = document.createElement("div");
dojo.byId("body").appendChild(placeHolder);
var tt = new dijit.Tooltip({label:"This is a test!<br>This is a test!<br>This is a test!", connectId:"someNode"}, placeHolder);
}
Enjoy!
just to make a note, as of
just to make a note, as of 1.0 final (or trunk from a few checkins before tagging) this was fixed. In theory, you don't need to create a node (unless you need it somewhere specific in the dom before initialization) when creating a widget. if no srcNodeRef is found, one is created (killing all the errors in contentpane, and other layout widgets). ymmv. I usually put my domNodes where i want them, then turn them into widgets, but this is just a simple failover i guess.
Node created automatically but has to be placed to document
As dante notes you don't need to create a new element. Even if you don't pass srcNodeRef when instantiating a new instance, the DOM structure of the widget instance will get created correctly (from the template). However, the widget will remain hidden since its DOM structure isn't attached to the document. You need to add a widget that was created without 'srcNodeRef ' to the document explicitly with DOM appendChild() or with Dojo.place(). For example:
// document.body.appendChild( innerPane.domNode )
// dojo.place( innerPane.domNode, dojo.body() )
dojo.place( innerPane.domNode, dojo.byId( 'someDiv' ), 'first' )
If this new widget should go inside another (container) widget, you can just do
accordionWidget.addChild( innerPane );and the child's domNode will be placed into container's containerNode automatically.In 1.2 we introduced a
In 1.2 we introduced a wrapper for dojo.place into dijit._Widget called .placeAt, which will place the widget's domNode using the same API as dojo.place, or alternately call addChild on a passed widget reference if it has one. Your above example can be written as:
or if you wish to add it to a borderContainer:
new dijit.TitlePane({ title:"inner" }).placeAt(bc); // calls bc.addChild(this)
A small fix
To make the example on this page clearer consider adding an id="someDiv" attribute to the inner pane so that it is clear this will be the target
Didn't work for me dijit.form.Button is not a constructor
Here's my code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Simple ComboBox</title>
<style type="text/css">
@import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
@import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css";
</style>
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
djConfig="parseOnLoad: true"></script>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.form.Button");
</script>
</head>
<body class="tundra">
<script type="text/javascript">
new dijit.form.Button({ "class": "large", style: "color: red" }, dojo.byId("someDiv"));
</script>
<div id="someDiv">
</div>
</body></html>
when I run it, nothing happens and I get the error: dijit.form.Button is not a constructor
from firebug
any suggestions?
regardless of where you have
regardless of where you have your "new dijit.form.Button" in the dom, it should be wrapped in an addOnLoad function, to ensure the required code has been fully loaded.
new dijit.form.Button({ "class": "large", style: "color: red" }, "someDiv");
});
just a note too: the second param to all Dijit constructors (where you have dojo.byId("someDiv")) accept either a node or string. It passes through dojo.byId() anyway ... my example above is slightly "cleaner"
TYVM,
TYVM,
I don't want to seem like a dork by saying, "OMG I can't believe you replied so quickly, and at 12:05AM on a Sunday, U R A God!" So I'll just sit here and think it. Anyway, thanks for the help, seems to have worked :)
Creating a tooltip programmatically
this foxed me for a while, but connectedId requires an array of strings, so
var tip4 = new dijit.Tooltip({ label : "Hello World", connectId : ["tip3"], showDelay : 0 });Should work in 1.1
Seems to break form validation
When I have a listener on form submission and add a new field dynamically, it doesn't seem to register the new validationTextBox with the validator.
Any thoughts?
Programmatically creating a dijit button inside of a dijit dialo
Hi,
Am attempting to use a dijit dialog box to display any xhr transport errors that occur. I am able to display the box successfully, however, I would like to have a button for the user to resubmit the ajax request. It seems that the event handlers do not function as expected. Specifically, I try to add an onclick handler to a button that is created inside the box, and the event is never registered. Interestingly enough, if I simply use the HTML markup to create the button, it works. I would like to make this work without this, it seems sort of... hackish... Anyone had an experience with this one?
Thanks!
Paul Mastin
Code is posted here:
this is all of the error handling function
console.info("XHR Transport Error.");
console.dir(ioArgs);
//console.dir(response);
var ioArgs = ioArgs; //make this available to our child functions
//build the nodes to display
var errorTxt = new dojo.NodeList(dojo.doc.createElement("p"));
//error message
if (ioArgs.xhr.status != 200) {
var msg = "There was an error while processing your request. This is likely the result of a faulty connection to the server. Please check your internet connection and resubmit your request.";
}
//assemble the response
//the form with the options to resubmit the request
var resubmitXHR = new dojo.NodeList(dojo.doc.createElement("form"));
resubmitXHR.attr("name", "resubmitXHR");
resubmitXHR.attr("id", "resubmitXHR");
var resubmitButtonParams = {
iconClass: "button_resubmit",
label: "Resubmit Request",
// Note here, when creating programmatically, this is a function, not a string
onClick: function() {
alert('clicked');
var orgRqst = {
url: ioArgs.args.url,
handleAs: ioArgs.args.handleAs,
postData: ioArgs.args.postData,
headers: ioArgs.args.headers,
load: ioArgs.args.load,
error: ioArgs.args.error
};
//submit it! if you fail, try, try again
dojo.rawXhrPost(orgRqst);
}
};
var resubmitButton = new dijit.form.Button(resubmitButtonParams, dojo.doc.createElement('div'));
resubmitXHR.adopt(resubmitButton.domNode, "end");
errorTxt.addContent(msg);
errorTxt.adopt(resubmitXHR);
var errorDialog = new dijit.Dialog({ title: "Transport Error" }, dojo.doc.createElement("div"));
errorDialog.setContent(errorTxt);
errorDialog.show();