Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dojo require() and AMD (1.7)

I'm having a heckuva time transitioning to Dojo and the new AMD structure, and I'm really hoping someone can shed some light on the whole concept. I've been living on Google for the last few weeks trying to find information on not the usage, but the structure and design pattern trends in using this.

I find it strange that for a relatively complex javascript application, such as for a main page where Dijits need to be created and styled, DOM elements created, etc, that I need to require, and therefore use, a TON of different modules that were otherwise available in the dojo namespace before the AMD system (or, at least, not assigned to 23 different vars).

Example:

require(['dijit/form/ValidationTextBox', 'dijit/form/SimpleTextarea', 'dijit/form/CheckBox', 'dijit/Dialog', 'dijit/form/Form']) require(['dojo/ready', 'dojo/parser', 'dojo/dom-style', 'dijit/registry', 'dojo/dom', 'dojo/_base/connect', 'dojo/dom-construct'],  function(ready, parser, style, registry, dom, event, construct){     //...etc } 

That's only a few of the modules for one of the pages I'm working on. Surely there's a better, non-breaking-in-future-releases way of accessing these methods, etc. I mean, do I really have to import an entirely new module to use byId()? And yet another to connect events? On top of that, all the clutter being created by having to assign a variable name in the functions argument list to cling to just seems like such a backstep.

I thought maybe you would require() the module only when needed, such as the query module, but if I need it more than once, then chances are the variable it's assigned to is out of scope, and I'd need to put it in a domReady! or ready call. reaalllly....??!

Which is why I can only assume it's my lack of understanding for dojo.

I really have looked and searched and bought books (albeit, a pre-AMD one), but this library is really giving me a run for my money. I appreciate light anyone can shed on this.

Edit for Example

require(['dijit/form/ValidationTextBox']) require(['dojo/ready', 'dojo/parser', 'dojo/dom-style', 'dijit/registry', 'dojo/dom', 'dojo/_base/connect', 'dojo/dom-construct'], function(ready, parser, style, registry, dom, event, construct){     /* perform some tasks */     var _name = new dijit.form.ValidationTextBox({         propercase : true,         tooltipPosition : ['above', 'after']     }, 'name')      /*     Let's say I want to use the query module in some places, i.e. here.     */     require(['dojo/query', 'dojo/dom-attr'], function(query, attr){         query('#list li').forEach(function(li){             // do something with these         })     }) } 

Based off of this format, which is used with many examples both from the dojo toolkit folks as well as third party sites, it would be, IMHO, absolutely ridiculous to load all the required modules as the first function(ready, parser, style, registy... would get longer and longer, and create problems with naming collisions, etc.

Firing up and require()ing all the modules I would need during the life of the script just seems silly to me. That being said, I'd have to look at some of the "package manager" scripts. But for this example, if I wanted to use the query module in select places, I would either have to load it up with the rest in the main require() statement. I understand why to an extent, but what's so bad with generic dot-syntax namespaces? dojo.whatever? dijit.findIt()? Why load module, reference in a unique name, pass through closure, blah blah?

I wish this were an easier question to ask, but I hope that makes sense.

Exasperation

Call me a newb, but this is really.. really.. driving me mad. I'm no noob when it comes to Javascript (apparently not) but wow. I cannot figure this out!

Here's what I'm gathering. In adder.js:

define('adder', function(require, exports){     exports.addTen = function(x){         return x + 10     } }) 

In some master page or whatever:

require(['./js/cg/adder.js']) 

...which doesn't follow the neat require(['cg/adder']) format but whatever. Not important right now.

Then, the use of adder should be:

console.log(adder.addTen(100)) // 110 

The closest I got was console.log(adder) returning 3. Yep. 3. Otherwise, it's adder is not defined.

Why does this have to be so difficult? I'm using my noob card on this, cause I really have no idea why this isn't coming together.

Thanks guys.

like image 658
Phix Avatar asked Feb 08 '12 00:02

Phix


People also ask

What is AMD in Dojo?

The Asynchronous Module Definition (AMD) format is the module format that Dojo adopted starting with Dojo 1.7. It provides many enhancements over the legacy Dojo module style, including fully asynchronous operation, true package portability, better dependency management, and improved debugging support.

What is AMD require?

AMD provides some CommonJS interoperability. It allows for using a similar exports and require() interface in the code, although its own define() interface is more basal and preferred. The AMD specification is implemented by Dojo Toolkit, RequireJS, and other libraries.

What is Dojo loader?

Dojo was among the first JavaScript libraries to define a module API and publish a loader and build application to solve all of these problems. The original API included the functions dojo. require (request a module), dojo. provide (define a module), and other supporting functions.

What is Dojo package?

A JavaScript toolkit that saves you time and scales with your development process. Provides everything you need to build a Web app. Language utilities, UI components, and more, all in one place, designed to work together perfectly. Get Dojo.


1 Answers

The dependency array format:

define(["a", "b", "c"], function (a, b, c) { }); 

can indeed be annoying and error-prone. Matching up the array entries to function parameters is a real pain.

I prefer the require format ("Simplified CommonJS Wrapper"):

define(function (require) {     var a = require("a");     var b = require("b");     var c = require("c"); }); 

This keeps your lines short and allows you to rearrange/delete/add lines without having to remember to change things in two places.

The latter format will not work on PS3 and older Opera mobile browsers, but hopefully you don't care.


As for why doing this instead of manually namespacing objects, @peller's answer gives a good overview of why modularity is a good thing, and my answer to a similar question talks about why AMD and module systems as a way of achieving modularity are a good thing.

The only thing I would add to @peller's answer is to expand on "paying attention to dependencies actually makes for much better code." If your module requires too many other modules, that's a bad sign! We have a loose rule in our 72K LOC JavaScript codebase that a module should be ~100 lines long and require between zero and four dependencies. It's served us well.

like image 165
Domenic Avatar answered Sep 29 '22 00:09

Domenic