PDA

View Full Version : sample setter class


yoDon
09-02-2004, 03:56 PM
I spent most of the afternoon figuring out how to use setters to initialize member objects.

In case anyone else is interested, here's what I came up with:


<class
name="SampleSetterClass"
extends="view">
<attribute name="Label" type="string" value="...loading..." setter="_setLabel(Label)"/>
<attribute name="Value" type="string" value="...loading..." setter="_setValue(Value)"/>
<attribute name="_initialLabel" type="string"/>
<attribute name="_initialValue" type="string"/>
<method name="_setLabel" args="t">
if ( typeof(this.implLabel)!="undefined" )
{ this.implLabel.setText( t ); }
else
{ this._initialLabel = t; }
</method>
<method name="_setValue" args="t">
if ( typeof(this.implValue)!="undefined" )
{ this.implValue.setText( t ); }
else
{ this._initialValue = t; }
</method>
<method name="init">
super.init();
if ( typeof(this._initialLabel)!="undefined" )
{ this._setLabel( this._initialLabel ); }
if ( typeof(this._initialValue)!="undefined" )
{ this._setValue( this._initialValue ); }
</method>
<simplelayout axis='x'/>
<text name="implLabel" width="120"/>
<text name="implValue" />
</class>


The class creates a composite object (a view containing two text objects) where the text properties of the child objects can be initialized and changed by setting attributes on the parent object.

An example usage for the class is

<view>
<simplelayout axis='y'/>
<SampleSetterClass name="Foo" Label="First" Value="good"/>
<SampleSetterClass name="Bar" Label="Second" Value="bad"/>
</view>

//Note: after the objects are created, the
// displayed text can be manipulated
// via commands like Foo.Label="Third"

The challenge was that class attributes are created and initialized before class member objects are constructed, so the initial setter call needs to temporarily stash the value on a dummy attribute until it can be recovered once the object is fully initialized (and all member objects have been constructed).

(WEB-INF/lps/components/lz/edittext.lzx was my starting place on this, but it made use of a _initcomplete attribute only found on components derived from text. The view class didn't seem to provide an _initcomplete attr, so I decided I'd build my classes using ( typeof(member)!="undefined" ) since that approach should work regardless of the base class.)

enjoy,
-Don

yoDon
09-02-2004, 05:15 PM
Hmmm...

If you want to modify the properties of an existing object, it looks like the syntax of the code matters. You apparently can't just use

Foo.Label="Third";

to modify the properties of existing objects because that doesn't seem to cause the setter to fire. Instead, you need to use something like

Foo.SetAttribute( 'Label' , "Third" );

That's annoying, but I guess I can live with it for now.

-Don

antun
09-02-2004, 05:24 PM
Nice work - but I think you can use constraints to achieve the same result:

<class name="mycomposite">
<attribute name="sometext" type="string" value="..." />
<text width="150" text="${parent.sometext}" />
</class>

If you want to modify the properties of an existing object, it looks like the syntax of the code matters...

That's right - your first example will set the value of Label to "Third", but it won't send the onLabel event, so nothing will update. Calling setAttribute sends the correct event.

-Antun

yoDon
09-04-2004, 02:47 PM
Originally posted by antun
[B]Nice work - but I think you can use constraints to achieve the same result:

<class name="mycomposite">
<attribute name="sometext" type="string" value="..." />
<text width="150" text="${parent.sometext}" />
</class>


I wasn't able to get nested composite classes (class mycompositeA contains several mycompositeB objects) to initialize correctly when I used constraints.

Using setters, the nested classes initialize correctly (subject to one big gotcha, as follows...)

<view datapath="DsFoo:/Item">
<simplelayout axis='y'/>
<text text="$path{'@MyArg'}"/>
<Composite MyArg="$path{'@MyArg'}"/>
</view>

Assuming Composite is a nested setter class, the code above will populate correctly as long as the datasource only contains a single Item.

If the datasource contains more than one Item, the text nodes are correctly instantiated but the Composite nodes are all left in their default state (as if they were just <Composite/>).

-Don

antun
09-07-2004, 08:50 AM
Assuming Composite is a nested setter class, the code above will populate correctly as long as the datasource only contains a single Item.

If the datasource contains more than one Item, the text nodes are correctly instantiated but the Composite nodes are all left in their default state (as if they were just <Composite/>).

If there are more than one Item nodes in the dataset, then your outer <view> tag will replicate. Are you perhaps seeing this behavior? If you put a simplelayout tag at the same level of the the view tag, you should be able to see if that is the case.

-Antun

yoDon
09-07-2004, 09:41 AM
It wasn't in my post, but in my code I do have an outer <view> with a simplelayout.

I am seeing many pairs of <text> nodes and <Composite> nodes, one for each item in the dataset.

The <text> nodes are all correctly rendered but the <Composite> nodes are rendered with their default values (as if the MyArg="$path{'@MyArg'}" line was missing).

-Don