Referencing other component in after:

35 views
Skip to first unread message

Hendrik Jan van Meerveld

unread,
Dec 1, 2013, 4:06:46 PM12/1/13
to cuj...@googlegroups.com
Hello,

I could use some help with this:

I've got a wire spec with two components of interest.

The first is a borderContainer:
  borderContainer: {
    create: {
      module: 'dijit/layout/BorderContainer',
      args: [
        {
          gutters: false,
          isLayoutContainer: true,
          liveSplitters: true,
          persist: false
        },
        { 
          $ref: 'id!borderContainer'
        }
      ]
    }
    //, ready: 'startup'

  },

This one works fine and "startup()" works fine when I un-comment that line.

Inside the borderContainer is a contentPane inside which is a dynamically drawn table (sitePen's dGrid):

  imageGrid: {
    create: {
      module: 'modules/horizontalDgrid/module',
      args: {
        node:  {$ref: 'id!all-images'},
        store: {$ref: 'imageStore'},
        field: 'id',
        label: 'description',
        query: {},
        render: { module: 'modules/horizontalDgrid/renderers/Image' }
      }
    },
    // ready: 'borderContainer.startup'
  },

What I am trying to do (but failing) is to call the startup method from borderContainer after imageGrid is finished drawing it's table.
The problem being that an error is thrown:

TypeError: target is null

So my question: Is it possible to call a method on one module after another module is ready? How would I do that?

Kind regards and thanks for any help,
Hendrik Jan


Hendrik Jan van Meerveld

unread,
Dec 1, 2013, 5:45:11 PM12/1/13
to cuj...@googlegroups.com
Hello,

I did find a solution.
I added imageGrid as a dependency of borderContainer like this:

  borderContainer: {
    create: {
      module: 'dijit/layout/BorderContainer',
      args: [
        {
          gutters: false,
          isLayoutContainer: true,
          liveSplitters: true,
          persist: false,
          imageGrid: {$ref: 'imageGrid'}, // here to force bordercontainer after dgrid
          contentPaneTop: {$ref: 'contentPaneTop'}, // and after contentPaneTop
          contentPaneLeft: {$ref: 'contentPaneLeft'}, // and after contentPaneLeft
          contentPaneRight: {$ref: 'contentPaneRight'}, // and after contentPaneRight
        },
        { 
          $ref: 'id!borderContainer'
        }
      ]
    },
    ready: 'startup'

  },

It fixes the problem, because it makes borderContainer execute after all other components are loaded.

Is there a more elegant syntax to force order of component creation?

Kind regards,
Hendrik Jan

unscriptable

unread,
Dec 3, 2013, 10:57:33 AM12/3/13
to cuj...@googlegroups.com
Hello Hendrik Jan,

This seems like one of those situations where two opposing patterns collide.  On one side, you've got DI: a component, borderContainer, expects that it'll be handed its dependency, imageGrid.  On the other side, dijit's compositional pattern references dependencies (i.e. imageGrid) from inside the parent (borderContainer).  To wire.js, the dependency from borderContainer to imageGrid is implicit since it can't see it.  

The method you used, creating an explicit dependency, will work, of course, but is redundant from a broader view.  

We have a dojo/dijit wire plugin that might help.  I don't know if we've tested it with recent versions of dojo, tbh.  https://github.com/cujojs/wire/blob/master/dojo/dijit.js

If you include the `wire/dojo/dijit` plugin in the spec (e.g. `$plugins: ['wire/dojo/dijit']`), you gain access to a few dijit-specific features, including a `placeAt` facet that uses `dijit.placeAt`.  

This plugin would allow you to move the imageGrid dependency out of borderContainer and into the wire spec, IIUC.

Does this help?

-- John

Hendrik Jan van Meerveld

unread,
Dec 3, 2013, 12:44:38 PM12/3/13
to cuj...@googlegroups.com
Hi Jonh,

Thank you so much for taking time to respond.
Your way of thinking in implicit and explicit dependencies is interesting and wire/dojo/dijit is new to me.

There is some information that I post now, that didn't seem important before.
The HTML that I am using is this (slightly edited):
<div id="borderContainer">
<div id="contentPaneTop">
<div id="imageGrid"></div>
</div>
<div id="contentPaneLeft"></div>
<div id="contentPaneRight"></div>
</div>

And I used dojo/dijit/BorderContainer, dojo/dijit/ContentPane and dGrid to target those div's.

It turned out that there is no dependency between borderContainer and imageGrid, but there is a dependency between borderContainer and contentPane.
Because the HTML structure already describes the layout of the contentPanes and borderContainers, it feels like redundant to use 'placeAt'.

So in the end I removed the imageGrid dependency but needed to keep the contentPane's dependencies (because the contentPanes need to be initialized before the borderContainer executes 'startup').
  borderContainer: {
    create: {
      module: 'dijit/layout/BorderContainer',
      args: [
        {
          gutters: false,
          isLayoutContainer: true,
          liveSplitters: true,
          persist: false,
          contentPaneTop: {$ref: 'contentPaneTop'}, // here to force bordercontainer after contentPaneTop
          contentPaneLeft: {$ref: 'contentPaneLeft'}, // and after contentPaneLeft
          contentPaneRight: {$ref: 'contentPaneRight'}, // and after contentPaneRight
        },
        { 
          $ref: 'id!borderContainer'
        }
      ]
    },
    ready: 'startup'

  },

I am new to DI and it is not yet easy to have a broader view.
For now I stick with my own solution (and am happy with it) but any suggestions for more elegant code are welcome.

Kind regards,
Hendrik Jan

unscriptable

unread,
Dec 3, 2013, 12:52:56 PM12/3/13
to cuj...@googlegroups.com
Ah, yes, the interesting part (to me) is that you are using the HTML as a composition plan (as is the dijit way) as well as wire.js as a composition plan.  We've been thinking a lot lately about using the HTML as the composition plan.  I think it makes a lot of sense when considering the proposed WebComponents spec.  

Regards,

-- John

Hendrik Jan van Meerveld

unread,
Dec 10, 2013, 12:25:03 PM12/10/13
to cuj...@googlegroups.com
Hi John,

First of all, this is all new to me so I am fiddling around
The reasons I chose this setup are these:

  • Placing the layout components in the HTML
    •   Seems logical to me because HTML is made for layout.
    •   That way the DOM nodes are allready in place and don't have to be moved to a final location.
    •   I found that the TodoMVC example for Cujojs starts up with a blank screen while the xhr requests are being processed. This give the application a slow feeling. By placing the layout components in the HTML they can already be displayed before the Javascript kicks in.
  • Placing the programming components in wire.js
    • I want to explore wire.js to gain a better understanding of DI
    • I could have placed all properties in a 'data-dojo-prop' attributes in the HTML, but than I would have needed 'dojo/parser' and I don't like the idea of some code traversing the DOM to find attributes

Kind regards,
Hendrik Jan
Reply all
Reply to author
Forward
0 new messages