Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dojo 1.7: BorderContainer and ContentPanes not working inside of a custom widget template

Tags:

dojo

This is similar to a question already on here but I'm using Dojo 1.7. So, I can't get BorderContainer and ContentPanes working inside of a custom widget template. It's driving me mad. I tried adding the mixins suggested in the other post and it didn't work.

So I have two examples. The first is a single page using dojo declaratively and it works fine. The second example is exactly the same page but I use a widget to embed the template. It renders the widgets but they are all stuck together in the top right corner. Same page, same styles. BUT, when i resize the browser window the page takes shape. There are still bits missing but it's better

Many thanks

This is the first example, which works

<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Demo: Application Controller</title>
    <link rel="stylesheet" href="/js/tag/widgets/BorderWidget/css/demo.css" media="screen">
    <link rel="stylesheet" href="/js/tag/widgets/BorderWidget/css/style.css" media="screen">
    <link rel="stylesheet" href="/js/dijit/themes/claro/claro.css" media="screen">

    <!-- Configure Dojo -->
    <script type="text/javascript">
      var djConfig = {
        isDebug : true,
        parseOnLoad : true
      };
    </script>
    <script type="text/javascript" src="/js/dojo/dojo.js"></script>
    <script>
      dojo.require("dijit.layout.BorderContainer");
      dojo.require("dijit.layout.TabContainer");
      dojo.require("dijit.layout.ContentPane");
    </script>
  </head>
  <body class="claro">
    <div style="height:100%">
      <div id="appLayout" class="demoLayout" data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="design: 'headline'">
        <div class="centerPanel" id="tabs" data-dojo-type="dijit.layout.TabContainer" data-dojo-props="region: 'center', tabPosition: 'bottom'">
          <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="title: 'About'">
            <h2>Flickr keyword photo search</h2>
            <p>
              Each search creates a new tab with the results as thumbnails
            </p>
            <p>
              Click on any thumbnail to view the larger image
            </p>
          </div>
        </div>
        <div class="edgePanel" data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region: 'top'">
          <div class="searchInputColumn">
            <div class="searchInputColumnInner">
              <input id="searchTerms" placeholder="search terms">
            </div>
          </div>
          <div class="searchButtonColumn">
            <button id="searchBtn">
              Search
            </button>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>

And this is second example using a widget

<!DOCTYPE HTML>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Demo: Application Controller</title>
    <link rel="stylesheet" href="/js/tag/widgets/BorderWidget/css/demo.css" media="screen">
    <link rel="stylesheet" href="/js/tag/widgets/BorderWidget/css/style.css" media="screen">
    <link rel="stylesheet" href="/js/dijit/themes/claro/claro.css" media="screen">

    <!-- Configure Dojo -->
    <script type="text/javascript">
      var djConfig = {
        isDebug : true,
        parseOnLoad : true,
        paths : {
          'tag' : '../tag/widgets/BorderWidget'
        }
      };
    </script>
    <script type="text/javascript" src="/js/dojo/dojo.js"></script>
    <script>
      dojo.require("dijit.layout.BorderContainer");
      dojo.require("dijit.layout.TabContainer");
      dojo.require("dijit.layout.ContentPane");
      dojo.require('tag.Widget');

      dojo.ready(function() {
        new tag.Widget().startup();
      });
    </script>
  </head>
  <body class="claro">

  </body>
</html>

This is the widget code

define('tag/Widget', 
[
  'dojo', 
  'dijit/_Widget', 
  'dijit/_TemplatedMixin', 
  'dijit/_WidgetsInTemplateMixin',
  'dijit/layout/BorderContainer',
  'dijit/layout/TabContainer',
  'dijit/layout/ContentPane'
], 
function(d) {
  //The widget contructor will be returned
  return d.declare('tag.Widget', 
  [
    dijit._Widget, 
    dijit._TemplatedMixin, 
    dijit._WidgetsInTemplateMixin
  ], 
  {
    templateString : d.cache("tag", "templates/template.html"),

    postCreate : function() {
      this.inherited(arguments);
      var domNode = this.domNode;
    },

    startup : function(args) {
      this.inherited(arguments);
      this.placeAt(dojo.doc.body);
    }


  });
});

This is the template for the widget

<div style="height:100%">
  <div id="appLayout" class="demoLayout" data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="design: 'headline'">
    <div class="centerPanel" id="tabs" data-dojo-type="dijit.layout.TabContainer" data-dojo-props="region: 'center', tabPosition: 'bottom'">
      <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="title: 'About'">
        <h2>Flickr keyword photo search</h2>
        <p>
          Each search creates a new tab with the results as thumbnails
        </p>
        <p>
          Click on any thumbnail to view the larger image
        </p>
      </div>
    </div>
    <div class="edgePanel" data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region: 'top'">
      <div class="searchInputColumn">
        <div class="searchInputColumnInner">
          <input id="searchTerms" placeholder="search terms">
        </div>
      </div>
      <div class="searchButtonColumn">
        <button id="searchBtn">
          Search
        </button>
      </div>
    </div>
  </div>
</div>
like image 208
screenm0nkey Avatar asked Oct 27 '11 11:10

screenm0nkey


4 Answers

You might need to explicitly call startup on the BorderContainer and ContentPane layout widgets in your own startup() method. Also you probably want to always have this.inherited(arguments) in any of the widget lifecycle methods if you are overriding and inheriting method.

startup : function(args) {
    this.inherited(arguments);
    //console.log('asdasd')
    dojo.empty("body");
    this.placeAt('body');

    this.subContainerWidget.startup();
    //I think the border container will automatically call startup on its children 
    //(the content panes), but you may also need to call startup on them.
}

Also, as @missingno mentioned, you probably don't want to be emptying the <body> and replacing it during widget startup, as a general reusability thing.

like image 125
BuffaloBuffalo Avatar answered Oct 19 '22 01:10

BuffaloBuffalo


I had a very similar problem with a custom Widget and BorderContainers within and it finally worked after I inherited BorderContainer instead BaseWidget or _Widget. Hope that also helps in your case!

like image 26
skython Avatar answered Oct 19 '22 01:10

skython


I'm creating my templated custom widgets which contain BorderContainers with a surrounding div (because I couldn't get a top-level BorderContainer to work), like so:

<div style="height: 100%;">
<div style="height: 100%;" data-dojo-type="dijit/layout/BorderContainer"
     data-dojo-attach-point="bc"
     data-dojo-props="design: 'headline', gutters: false">
    <div data-dojo-type="dijit/layout/ContentPane"
         data-dojo-props="region: 'top'">
    </div>
    <div data-dojo-type="dijit/layout/ContentPane"
         data-dojo-props="region: 'center'">
    </div>
</div>

I had the exact same layout problems (BorderContainer would only layout correctly after page resize), until I realized (thanks to the answer by John Brinnand above) that I need to forward any resize calls from dijit to the "inner" BorderContainer. So what I did was to implement a resize method in my widget ("bc" is the BorderContainer widget, brought in via data-dojo-attach-point as seen in the above code):

        resize: function () {
        this.bc.resize(arguments);
        this.inherited(arguments);
    }

and lo and behold: everything works fine.

(I'm using dojo 1.9, but this should work for dojo >= 1.7)

like image 2
Oliver Avatar answered Oct 19 '22 03:10

Oliver


BorderContainer is a layout widget that needs to be dinamically sized. You have overwritten the startup method and I'd bet this is at least one of the problems.

Since your startup method contents aren't really startupy, I'd suggest you just try removing or renaming it (to expose the original startup).

d.declare(...)|{
    ...
    toFullScreen: function(){
        dojo.empty("body");
      this.placeAt('body');
    }
}

var w = new FlickApiView({...});
w.toFullScreen();
w.startup();

Edit (for the new problem):

I find

startup : function(args) {
  this.inherited(arguments);
  this.placeAt(dojo.doc.body);
}

to be suspicious, since all the resizing is done in the this.inherited part before the widget is actually placed (so the resizing doesn't work initially)

You could try switching the order here but I think it is better to just remove the startup method entirely and change the main to

var w  = new tags.Widget();
w.placeAt(dojo.body());
s.startup();
like image 1
hugomg Avatar answered Oct 19 '22 02:10

hugomg