Search code examples
amddojo

How to know which Dojo AMD require clause with no name?


I have a question on Dojo declaration. I noticed in the AMD declaration for required library for dojo that some library does not have declared name in the funciton parameter. How do you know which one has no parameter?

For example:

For selector query, I saw an example which does not give name for dojo/NodeList-dom and dojo ready.

require(["dojo/query", "dojo/dom-class", "dojo/on", "dojo/NodeList-dom", "dojo/domReady!"], function(query, domClass, on) {

Is it just optional to give them names? So if I do not want a declaration for their name, I should place them in the end of the list?

Or can I give them arbitrary names? I saw some example that gives names to domReady with a variable named "request".

I am assuming that this is correct?

require(["dojo/query", "dojo/dom-class", "dojo/on", "dojo/NodeList-dom", "dojo/domReady!"], function(query, domClass, on, nodeList, request) {

While this is not?

// No name for NodeList-dom
require(["dojo/query", "dojo/dom-class", "dojo/on", "dojo/NodeList-dom", "dojo/domReady!"], function(query, domClass, on, request) {

Also, how do you know if you need name for them, can I just not name any of them?


Solution

  • You can choose what you name and what not. It depends on what the module does and if you need the callback parameter in order to work with it. For example, the dojo/query module is useful for querying DOM nodes, but you can't use it without an actual reference to it (the function parameter).

    On the other hand, modules like dojo/NodeList-dom extend the dojo/query module, you won't need their callback to do stuff with it.


    Widgets can be useful with or without callback parameter. If you use widgets declarative, you don't need the callback while if you create them programmatically, you need the widget to instantiate it, for example:

    require(["dijit/form/FilteringSelect"], function(FilteringSelect) {
        return new FilteringSelect({});
    });
    

    While declaratively you only need:

    require(["dijit/form/FilteringSelect", "dojo/parser"], function() {
    
    });
    

    But even if your module has no purpose to have a callback parameter (for example dojo/NodeList-dom), you can still name them anyway:

    require(["dojo/NodeList-dom"], function(NodeList) {
    
    });
    

    But they won't be useful to you. So you can in fact name all modules if you find that easier.

    The best way to find out if you need to name it or not, is by looking at how they're used at the reference guide. If you see that the callback parameter is used to call the module functions, for example:

    require(["dojo/query", "dojo/NodeList-dom", "dojo/domReady!"], function(query) {
        query("#myNode").forEach(function(node) {
            console.log(node);
        });
    });
    

    We use the query callback to query #myNode, so we need to name it. However, the dojo/NodeList-dom extends the query (with for example the forEach() function) so we don't need to name it.

    The dojo/domReady! module/plugin doesn't have to be named either. This module will make sure that the callback function is only called when the DOM is loaded.


    One important note is that the order of the callback parameters is the same as the order of the modules. Even if a module doesn't return a proper object you can use, it still counts. For example (the following will not work):

    require(["dojo/NodeList-dom", "dojo/query", "dojo/domReady!"], function(query) {
        query("#myNode").forEach(function(node) {
            console.log(node);
        });
    });
    

    Many people think that, because dojo/NodeList-dom doesn't return a useful object, they can just leave it that way, but that isn't true. The query callback parameter will actually contain the data that is returned by dojo/NodeList-dom in this example (because it's the first parameter) whatever that data may be.

    So if you don't actually need the callback parameter of the module, the easiest thing is to add it to the end of the module list or you could do the following (as I explained before):

    require(["dojo/NodeList-dom", "dojo/query", "dojo/domReady!"], function(NodeList, query) {
        query("#myNode").forEach(function(node) {
            console.log(node);
        });
    });
    

    This example will work, however, for other developers (reading your code) it may be confusing because they might think they can use the NodeList parameter. So for the sake of keeping your code readable, I suggest you just put dojo/NodeList-dom at the end of the module list.


    Now let's see if we can answer your code examples:

    Your first example is correct, as I just explained. dojo/NodeList-dom and dojo/domReady! do not return useful objects, so you can leave them out.

    Your second example is correct as well. You can choose to name these modules anyway, even if you don't use their callback.

    The third example is also correct, however the request parameter will contain the dojo/NodeList-dom callback and not the dojo/domReady! callback. You may choose how you name them. Whether it works or not depends on what you're going to do with the request callback. I mean, the following example will work as well:

    require(["dojo/query", "dojo/NodeList-dom", "dojo/domReady!"], function(NodeList, domReady, query) {
        NodeList("#myNode").forEach(function(node) {
            console.log(node);
        });
    });
    

    But in this case, the NodeList callback parameter contains the result of dojo/query, domReady contains the result of dojo/NodeList-dom and query contains the result of dojo/domReady!. How confusing it may sound, it will work. But as you can see, to query #myNode I need the result of dojo/query, which is NodeList in this case. Confusing, isn't it? That's whŷ you should choose proper names.