Opened 10 years ago

Closed 10 years ago

Last modified 10 years ago

#14742 closed defect (fixed)

_WidgetsInTemplateMixin problematic with concurrent Dojo versions?

Reported by: fredfortier Owned by: bill
Priority: undecided Milestone: 1.8
Component: Dijit Version: 1.7.1
Keywords: Cc:
Blocked By: Blocking:


Background: I am trying to refactor an application to take advantage of Dojo 1.7.1. I am using async mode with AMD syntax. Sadly, my application widgets do not fully run standalone but in one of IBM's iWidget platform (Business Space V7 if it matters to anyone). So I need to work with two concurrent version of Dojo: 1.3.2 (IBM build for the BS stuff) and my custom namespaced 1.7.1 build.

Problem statement: I was able to create my custom Dojo build using custom packages name and run it together with IBM's build successfully (see details below) -- EXCEPT for one thing. IBM's Dojo becomes angry whenever I require "dijit/_WidgetsInTemplateMixin" in my code. I can create templated widgets fine as long as I set the Dijits programatically, but I can't get the app to parse the Dijit declared in the template without affect the Dojo 1.3.2 instance.

Symptoms: Here is my djConfig. I am setting insertAbsMids: 0 when generating my custom Dojo 1.7.1 build.

dojoConfig =
        has :
                "dojo-firebug" : true,
                "dojo-debug-messages" : true
        async : 1,
        parseOnLoad : true,
        baseUrl : '/lcsdojo/js/dojo-release-1.7.1-LCS/dojo/',
        packages : [
                name : 'lcsDojo',
                location : '/lcsdojo/js/dojo-release-1.7.1-LCS/dojo',
                packageMap :
                        dojo : 'lcsDojo',
                        dijit : 'lcsDijit',
                        dojox : 'lcsDojox'
                name : 'lcsDijit',
                location : '/lcsdojo/js/dojo-release-1.7.1-LCS/dijit',
                packageMap :
                        dojo : 'lcsDojo'
                name : 'lcsDojox',
                location : '/lcsdojo/js/dojo-release-1.7.1-LCS/dojox',
                packageMap :
                        dojo : 'lcsDojo',
                        dijit : 'lcsDijit',
                        dojox : 'lcsDojox'
                name : 'iWidget',
                location : '/CustomWidgets/catalog/com/td/dms/widgets/iWidget'
        deps : ['lcsDojo'],
        callback : function()
                require(['lcsDojo/domReady!'], function()
              "lcsDojo DOM Ready!");

Here is how I define and declare my custom widget. As pointed out, this code works fine if I do not use the _WidgetsInTemplateMixin "feature" (programatic syntax only).

define("iWidget/viewer/viewerWidget", [
"lcsDijit/_WidgetsInTemplateMixin", //<-----Code his works until I add this
], function(declare, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, template)
        declare("iWidget.viewer.viewerWidget", [_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin],
                templateString : template,
                workplaceGetContentUrl : null,

Here is what IBM Dojo 1.3.2 has to say about this from the FireBug? console output. It's Dijit object does not seem to be able to read its own registry anymore. I suspect that the Dijit registry is some sort of global variable without a different namespace in this case. NOTE: dojo.js in this case is the 1.3.2 version, not the custom namespaced 1.7.1.

dojo.byId is not a function
(?)()59 (line 257)
(?)()60 (line 940)
log()dojo.js (line 16)
[Break On This Error]

undefineddojo._scopeArgs = [undefined]; 

I looked at the source of dijit/_WidgetsInTemplateMixin.js. The snippet below caught my attention.

Could the scope: "dojo" line be the issue? Should this be scoped based on the Dojo package name?

                _beforeFillContent: function(){
                                // Before copying over content, instantiate widgets in template
                                var node = this.domNode;

                                var cw = (this._startupWidgets = parser.parse(node, {
                                        noStart: !this._earlyTemplatedStartup,
                                        template: true,
                                        inherited: {dir: this.dir, lang: this.lang, textDir: this.textDir},
                                        propsThis: this, // so data-dojo-props of widgets in the template can reference "this" to refer to me
                                        scope: "dojo" // even in multi-version mode templates use dojoType/data-dojo-type

                                this._supportingWidgets = registry.findWidgets(node);

                                this._attachTemplateNodes(cw, function(n,p){
                                        return n[p];

Change History (9)

comment:1 Changed 10 years ago by bill

Hmm, mysterious. I don't understand what's going on either although the error about:

undefineddojo._scopeArgs = [undefined]; 

That must be from bootstrap.js in dojo version 1.3, which does:

d._scopeArgs = [dojo, dijit, dojox];

I don't see the connection to the _WidgetsInTemplateMixin.js or to the parser though.

I think the "scope" parameter is OK; it just means that the parser from your dojo 1.7 instance will search for data-dojo-type/dojoType inside templates, rather than whatever you redefined scope too, for example data-dojo17-type/dojo17Type.

When _WidgetsInTemplateMixin calls the parser, I'd like to make sure that it's going to the 1.7 parser rather than the 1.3 parser. Can you trace that through firebug (or just with console.log() statements)? I guess your lcsDijit packageMap should handle that, but might as well confirm it.

You said you are working with two versions of dojo, but how about parsing the main document? Is the main document being parsed, and if so, are you running the parser from one version of dojo, or the other version, or trying to split parsing between the two versions? Are you setting parseOnLoad: true?

comment:2 Changed 10 years ago by ben hockey

also, try adding an entry for dijit: 'lcsDijit' to the lcsDijit packageMap. it may not be effective but i've found it to be necessary in the past - which is not to say that its still necessary now but its simple enough for you to try.


comment:3 Changed 10 years ago by fredfortier

@neonstalwart - yes, that was the issue. Pretty simple indeed. I am now able to import _WidgetsInTemplateMixin from my Dojo 1.7 package without impacting Dojo 1.3.2.

comment:4 Changed 10 years ago by bill

Milestone: tbd1.8
Owner: set to bill
Status: newassigned

Great, thanks @neonstalwart.

I see in _WidgetsInTemplateMixin.js and a few other files that we have absolute MIDs instead of relative ones. I'll fix that.

Last edited 10 years ago by bill (previous) (diff)

comment:5 Changed 10 years ago by ben hockey

ah... that would be why it's needed. i'd figured it would have to be something like that but never took the time to figure out why i needed the extra configuration when my understanding was that in theory it shouldn't have been needed (unless there were explicit references to dijit).

i think i also noticed a few places that have dependencies of just "." and those should probably be changed to "./main" to be safe.

comment:6 Changed 10 years ago by bill

OK, I'll fix dojo/ and dijit/.

dojox/ has a lot of errors and an increasing number of svn:external packages, so those updates will need to be left to the individual package owners.

comment:7 Changed 10 years ago by bill

Resolution: fixed
Status: assignedclosed

In [27778]:

Fix MID's in dojo/ and dijit/ modules to be relative paths (when possible), and convert "." --> "./main".

The "./main" references in dijit/ modules are for exporting symbols to the "dijit" namespace and thus will be removed in 2.0, but before that (for consistency) maybe it's worth changing the code to export via setObject(), like dojo.declare() does.

Fixes #14742 !strict.

comment:8 Changed 10 years ago by ben hockey

bill you missed a reference to dojo in dojo/robot but besides that, i think its better to export to dijit/main rather than using setObject. using setObject seems to imply that you mean to make something global whereas exporting to dijit/main would just seem to imply that you want to augment that single module (which might not necessarily be global if you config the loader appropriately). it may turn out that if you config the loader to not expose globals that setObject and augmenting dijit/main are still the same but i think by using dijit/main the intention is clearer. as you say, in 2.0 it all goes away so then it doesn't matter - i don't think dijit/main makes much sense in 2.0

comment:9 Changed 10 years ago by bill

In [27813]:

Fix a lingering non-relative MID, and convert ".." --> "../main", refs #14742 !strict

Note: See TracTickets for help on using tickets.