Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#18217 closed defect (invalid)

modules sharing works strange - all changes are in all parent widgets

Reported by: dojonovice@… Owned by: dojonovice@…
Priority: undecided Milestone: tbd
Component: Loader Version: 1.10.0
Keywords: Cc:
Blocked By: Blocking:

Description

I have a one strange issue. I tested it on isolated environment and everything works fine. But in nested structure I am not able to share modules. In some cases I get empty objects or all methods has undefined value but exists.

Problem description:

  • module1 for inheritance - sharing, no widget, only module without template, only logic (properties and methods), no constructor, no startup, define and declare are used.
  • widget1 define module1 and use it in declare - inheritance, widget1 has template, constructor and startup
  • widget2 define module1 and use it in declare - inheritance, widget2 has template, constructor and startup

if widget1 set any property in module1, automatically has same value widget2.

What is wrong? I have this issue on two projects. I thought that it is dgrid bug but it seems that it is dojo module loader/declare bug because dgrid is not used.

Change History (4)

comment:1 Changed 5 years ago by ben hockey

Owner: set to dojonovice@…
Status: newpending

do you have any code to go along with this? the best i can guess from your description is that you're not realizing that module1 is shared between the 2 widgets - this is working as expected. think of modules as singletons. once you request a module, if another module requests that same module, they both have a reference to the same object.

does that explain the problem you're seeing?

comment:2 Changed 5 years ago by dojonovice@…

Status: pendingnew

Posting simple short sample for check. Inside startup I set properties to settings. What I set to widget 1 I see in widget 2. What is wrong. In isolated testcase it works fine, independent. In nested structure I have this problem. Using mostly declarative style for rendering/parsing widgets. But this strange behavior has other consequences.

Short sample of module

define(["dojo/_base/declare",
  "dojo/aspect",
  "dojo/store/Memory",
  "dojo/store/Observable",
  "dijit/Tree",
  "dijit/tree/ObjectStoreModel",
  "dijit/tree/dndSource",
  "dijit/registry",
  "dojo/_base/lang",
  "dojo/dom-class"
],
        function(declare, aspect, Memory, Observable, Tree, ObjectStoreModel,
                dndSource, registry, lang, domClass) {
          return declare([], {

            settings: {
              data: null,
              getChildren: function(object) {
              },
              mayHaveChildren: function(item) {
              }
            },
            method : function() {
            } 
       
          });
        }
);

Short sample of widget 1, see startup

define([
  "dojo/_base/declare",
  "_WidgetTemplate", // contains other modules
  "dojo/text!./templates/Template.html",
  "module"
], function(declare, _WidgetTemplate, template, module) {

  return declare("widget-1", [
    _WidgetTemplate, module], {  

    templateString: template,

    constructor: function(object) {
    },
    startup: function() {
      this.inherited(arguments);
      this.settings.data = {name : "neonstalwart"};
    }
  });
});

Short sample of widget 2, see startup

define([
  "dojo/_base/declare",
  "_WidgetTemplate",
  "dojo/text!./templates/Template.html",
  "module"
], function(declare, _WidgetTemplate, template, module) {

  return declare("widget-2", [
    _WidgetTemplate, module], {  

    templateString: template,

    constructor: function(object) {
    },
    startup: function() {
      this.inherited(arguments);
      this.settings.data = {name : "bill"};

    }
  });
});
Last edited 5 years ago by ben hockey (previous) (diff)

comment:3 Changed 5 years ago by ben hockey

Resolution: invalid
Status: newclosed

this is working exactly as expected.

  1. widget 1 and widget 2 get a reference to the same mixin/class you return from module.
  2. the settings object you've set on the prototype is shared amongst all instances derived from module.

to get around this, you need to avoid putting an object (i.e. settings) on the prototype. you can either flatten it out and put the data, getChildren, and mayHaveChildren properties directly on your class or you can add some extra code to create a unique settings object per instance

return declare([], {
    settings: null,
    postMixInProperties: function () {
        this.inherited(arguments);

        // any settings passed to the constructor would now be at this.settings.
        // this will use those to override/augment our default settings.
        // this creates a new settings object per instance 
        // and does not mutate any settings passed in from the user.
        this.settings = lang.mixin({
            data: null,
            getChildren: function (object) { },
            mayHaveChildren: function (item) { }
        }, this.settings);
    }
});

since there is no bug, i'm closing this ticket. if you need more help to understand what is happening here and why, please seek help via the mailing list, irc, stackoverflow, etc.

comment:4 Changed 5 years ago by dojonovice@…

Thanks, it works. This information is very important/useful. I was searching it on internet, but haven't found information that this case can cause a problem and I must use postMixInProperties for this.

Last edited 5 years ago by dojonovice@… (previous) (diff)
Note: See TracTickets for help on using tickets.