Widget Composition - Parent acces problem

Hello,

I have created a custom window. When instanciated, this window create 2 other widgets inside it : windowHeader & windowContent, which have their own methods...

My issue concern the window attributes access from the child elements windowHeader & windowContent.

In fact, I can access them throw the debugger, but not in my code. So the following 2 solutions don't work :
- With parent controller :

        var contWindow = bb.getControllerFromModel(this.modelNode.parentNode);
        var moduleList = contWindow.getAttribute('displayedModule');

- Via XPath :
        var moduleList = bb.evaluateSmart('string(./../@displayedModule)', this.modelNode);

The only solution that I found is to duplicate attribute of the window in the windowHeader & windowContent when I create them :

<d:constructor >
        <c:create destination="." mode="appendChild">
                <trad:windowHeader>
                        <c:attribute name="title" select="string(./@title)" />
                        <c:attribute name="type" select="string(./@type)" />
                </trad:windowHeader>
                <trad:windowContent>
                        <c:attribute name="id" select="string(./@winId)" />
                        <c:attribute name="displayedModule" select="string(./@displayedModule)" />
                </trad:windowContent>
        </c:create>
</d:constructor>

With this solution I can acces attribute, but this is not optimal. For ex, when I update the window attribute "displayedModule", I have to update the windowContent attribute "displayedModule"...

Do you know why I can't access parent attributes from child elements ?
Do you have a better solution ?

Cheers.

Re: Widget Composition - Parent acces problem

WebDev1,

Although the practice you exercise is not very well developed in the Backbase framework, you can still achieve your goal!

First, please note: you cannot access the parent element in the constructor. This is done by design, in the constructor you only have access to your own instance (just imagine you would do: bb.document.createElementNS("yournamespace", "yourelement"), what would be the parent element then?)

In the code below I changed d:constructor to d:handler for DOMNodeInsertedIntoDocument event, in theory this should work for you, please try!

<d:handler event="DOMNodeInsertedIntoDocument" type="application/xml">
        <c:create destination="." mode="appendChild">
                <trad:windowHeader>
                        <c:attribute name="title" select="string(./@title)" />
                        <c:attribute name="type" select="string(./@type)" />
                </trad:windowHeader>
                <trad:windowContent>
                        <c:attribute name="id" select="string(./@winId)" />
                        <c:attribute name="displayedModule" select="string(./@displayedModule)" />
                </trad:windowContent>
        </c:create>
</d:handler>

Sergey/

Sergey, Ok, I didn't provide

Sergey,

Ok, I didn't provide enough explanation regarding my problem. In fact, the sample of code I wrote refers to the window constructor. This code should probably be more clear :

<d:element name="window">
        <d:attribute name="winId"/>    
        <d:attribute name="title" />
        <d:attribute name="type" default="generic" />
        <d:attribute name="displayedModule" default="" />
        <d:constructor >
                <c:create destination="." mode="appendChild">
                        <trad:windowHeader>
                                <c:attribute name="title" select="string(./@title)" />
                                <c:attribute name="type" select="string(./@type)" />
                        </trad:windowHeader>
                        <trad:windowContent>
                                <c:attribute name="id" select="string(./@winId)" />
                                <c:attribute name="displayedModule" select="string(./@displayedModule)" />
                        </trad:windowContent>
                </c:create>
        </d:constructor>
</d:element>

This look like dummy code, cause I just "copy / paste" attributes of the parent node (window) in the child nodes (windowHeader, windowContent). As I said the reason is that I can't access to window attribute from windowHeader, windowContent (with the prevoius described methods).

But in fact you are right, after, I call the parent attribute from the son's constructor and this is not possible. I have tried with the event handler and it NEARLY works...

Event "DOMNodeInsertedIntoDocument" is fire too much time. I have tried to create a custom event fire from the parent at construction time, but it doesn't work cause sons aren't built at this time...

Any other solution ?
Or do I need to refactor my whole code to get a single widget instead of a widget composed of many widgets?

In fact, I don't know what is the best practice, but from pure logical view, widget composition make sense for my application... it also reduce dependencies between funtionnality and make the code more "readable".

Hi Webdev1, You could create

Hi Webdev1,
You could create a property in the windowHeader and the windowContent that point to the parent. You could fill this property when you construct the widget. See the Photostrip example in the Widget Development Guide for an example of this.

In the Widget Development Guide there is an extensive discussion on creating composite widgets, with examples. Maybe you could take a look at it. If you have more questions then, please feel free to ask. Certainly you should be able to compose widgets like building blocks into larger widgets.

Which version of the Client Framework do you use? There was a bug fixed about DOMNodeInsertedIntoDocument firing too many times. This was fixed for version 4.2.0.

Cheers, Ghica.