belzebu
belzebu

Reputation: 820

Dojo : Inheriting/Extending templated widgets : How to?

I've created a templated base widget called "Dialog", which I want to use as a core layout widget for all the other within the package. It's a simple container with couple of attach points. (I've not included HTML as it's quite straightforward)

define("my/Dialog",[
"dojo/_base/declare",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
"dojo/ready",
"dojo/parser",
"dojo/text!./Dialog.html"], function(declare, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, ready, parser, template){

return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {

    templateString: template,
    widgetsInTemplate: true,

    title: 'Dialog',        
    content: null,

    constructor: function(args){
    },

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


    ///
    /// Getters / Setters
    ///

    _setTitleAttr: function(title){
    },

    _setContentAttr: function(content){
        this._contentPane.innerHTML = content;
    }       
});

ready(function(){
    parser.parse();
});});

Then I want to create another templated dialog that will inherit from this one, and will basically extend it in terms of kind-of-injecting the template into the content of the my/Dialog

define("my/BookmarksDialog",[
"dojo/_base/declare",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
"dojo/ready",
"dojo/parser",
"my/Dialog"], function(declare, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, ready, parser, Dialog){

return declare([Dialog, _WidgetsInTemplateMixin], {

    //templateString: template,

   template: '<div data-dojo-attach-point="bookmarkpoint">something</div>',

    widgetsInTemplate: true,
    content: template, // This works but doesn't parse the widgets within
    title: 'Bookmarks',

    constructor: function(args){
    },


    postCreate: function(){ 
        this.inherited(arguments);  
    }

});

ready(function(){
    parser.parse();
});});

The problem I'm facing is that the attach point called bookmarkpoint is not accessible for the BookmarkDialog

So the question is: How do I get the BookmarkDialog template get parsed and placed in the Dialog widget?

Options:

  1. Copy the template of the Dialog widget in to BookmarkWidget is not really an option,
  2. Instantiate the Dialog in the BookmarkWidget template is not much of an option either, as I don't want the Dialog to be under an attach point. I'd have to wrap all the methods of Dialog into BookmarkDialog to propagate correctly.

Please note that I'm also firing the .startup() upon instantiating the widget. Thanks

Upvotes: 5

Views: 5066

Answers (2)

belzebu
belzebu

Reputation: 820

Thanks for that, as I see I was trying to do the magic in wrong place "postMixInProperties"! This has actually led me to very similar solution and that is to simply replace the base widget's template string's variable with the template string of the enhancing widget.

Consider this base widget's template string. Please notice the {0}.

<div class="dialog" data-dojo-attach-event="onkeyup:_keyUp" >
<div data-dojo-attach-point="_wrapper" tabindex="1" role="button">
    <div data-dojo-attach-point="pendingPane"></div>
    <div class="inner commonBackground unselectable">
        <span class="hideButton" data-dojo-attach-point="closebtn" data-dojo-attach-event="onclick:close" aria-hidden="true" data-icon="&#xe00f;"></span>
        <div class="header" style="cursor: default;" data-dojo-attach-point="_titlePane"></div>
        <div data-dojo-attach-point="_contentPane" class="contentPane">{0}</div>
    </div>
</div>

Then the template string of the enhanced widget

<div class="bookmarks">
    <div data-dojo-attach-point="bookmarkpoint">
        test attach point
    </div>
</div>

And then in the enhanced widget's "buildRendering" I've used the following

return declare([Dialog], {      
    title: 'Bookmarks',

    constructor: function(args){
    },

    buildRendering: function(){
        this.templateString = lang.replace(this.templateString, [template]);
        this.inherited(arguments);
    },

    postCreate: function(){ 
        this.inherited(arguments);
        this._cookiesCheck();
    }, ...

where "template" variable comes from one of the requires

"dojo/text!./BookmarksDialog.html",

Maybe there is a simpler and kind of out-of-the-box way in dojo how to achieve the above mentioned, but this did the trick for me. Hope that helps!

Upvotes: 2

xxxmatko
xxxmatko

Reputation: 4142

Use buildRendering method, which is designed for this purpose. In this method you can parse templateString property, modify it and then reassign it.

buildRendering: function () {
    // Parse template string into xml document using "dojox/xml/parser"
    var xml = xmlParser.parse(this.templateString);
    var xmlDoc = xml.documentElement;

        // Find target node which should be modified
        var targetNode = query("div[data-dojo-attach-point='targetNode']", xmlDoc)[0];

    // Create new template content using createElement, createAttribute,  
        // setAttributeNode
        var newNode = xml.createElement("button");

    // Append content to the xml template
    targetNode.appendChild(newNode);

    // Re-set the modified template string
    this.templateString = xmlParser.innerXML(xmlDoc);

    this.inherited(arguments);
}

Upvotes: 4

Related Questions