PDA

View Full Version : call by reference: datapath


jocsch
10-16-2004, 08:01 AM
Hi,
I hope this an easy one for somebody with a deeper knowledge of datapathes (and/or replication):
I want to iterate programmatically over a dataset and create listitems from that.

The problem is that the pointer which is passed to the listitems changes as it iterates further and in the end all listitems have the same value. Have a look at the sample code:


<canvas debug="true">
<dataset name="default_items">
<items>
<item name="item1"/>
<item name="item2"/>
<item name="item3"/>
<item name="item4"/>
<item name="item5"/>
</items>
</dataset>

<class name="mylistitem" extends="listitem" height="20">
<view x="4" y="5" width="10" height="10"/>
<text datapath="@name"/>
</class>

<list id="a1" width="130" oninit="selectItemAt(1)" shownitems="6" datapath="default_items:/items">
<method event="ondata">
if ( this.datapath.selectChild() ){
recList(this,this.datapath);
}
</method>

<method name="recList" args="insertInto,top">
do {
var c = new mylistitem( insertInto ,{datapath:top});
}while (top.selectNext());

</method>
</list>
</canvas>


If you ask why I want to do it programmatically: Later, if the simple example works, I want to iterate over a tree structure (which I want to press into a list form). And this don't work with the declarative method, or?

Thanks,
Markus

mericson
10-16-2004, 10:05 AM
<canvas debug="true">
<dataset name="default_items">
<items>
<item name="item1"/>
<item name="item2"/>
<item name="item3"/>
<item name="item4"/>
<item name="item5"/>
</items>
</dataset>

<class name="mylistitem" extends="textlistitem" height="20" >
<view x="4" y="5" width="10" height="10"/>
<text datapath="@name"/>
</class>

<list id="a1" width="130">
<mylistitem datapath="default_items:/items/item"/>
</list>
</canvas>

jocsch
10-16-2004, 11:09 AM
That's want I want to avoid. This will work perfect for the given example. But what is with a structure like


<items>
<item name="item1">
<item name="item2"/>
<item name="item3">
<item name="item4"/>
</item>
</item>
<item name="item5"/>
<item name="item6"/>
<item name="item7"/>
</items>


This should fit into the list. That is not possible with the solution you suggested, or?
There I would need some JS logic behind, therefor I need to add the listitems programmatically.

mericson
10-16-2004, 11:51 AM
What results are you looking for with that dataset? Is your intent to do a depth-first walk of the tree?

Did you look at the tree examples in chapter 29 of the Developer's Guide?

To tell you the truth I'm bumping into perhaps a related wall. I want to create a reusable class for displaying subtrees of my XML and I'm struggling with the fact that a $path{} constraint is only evaluated at init time.

jocsch
10-16-2004, 12:34 PM
Yup. I want to have a list with


Item1
Item2
Item3
Item4
Item5
Item6


so that the children of a node come just after the node itself.

I worked with the tree example, but the difference is, that the example only need to iterate over the existing tree and work "one time" with every node (so the pointer can be reset everytime). In my example every pointer needs to keep "the state"/reference it had while traversing.
In the example they used the dupePointer function. Maybe that might help. Until now I had no success.

mericson
10-16-2004, 03:59 PM
The following seems to work. I also added an onclick to prove that the items all have unique datapaths.


<canvas debug="true">
<dataset name="default_items">
<items>
<item name="item1"/>
<item name="item2"/>
<item name="item3"/>
<item name="item4"/>
<item name="item5"/>
</items>
</dataset>

<class name="mylistitem" extends="textlistitem" height="20"
datapath="default_items:"
ondata="this.setAttribute('text', this.datapath.XPathQuery('@name'))"
onclick="foo.datapath.setPointer(this.datapath.p)" />

<view>
<simplelayout axis="x" spacing="10"/>

<list id="a1" width="130" oninit="selectItemAt(1)" shownitems="6" datapath="default_items:/items">
<method event="oninit">
if ( this.datapath.selectChild() ) {
recList(this,this.datapath);
}
</method>
<method name="recList" args="insertInto,top">
do {
var li = new mylistitem(insertInto);
li.datapath.setFromPointer(top);
}while (top.selectNext());
</method>
</list>

<text id="foo" text="$path{'@name'}"><datapath/></text>
</view>

</canvas>

jocsch
10-17-2004, 09:16 AM
hey mericson, many thanks for that solution.
If you don't mind, I want to take it to the top:

How to make this list data change aware? Simple example would be to replace the "onclick" with a

this.datapath.deleteNode()


The item is deleted in the dataset, but not in the list. OK, I think that would be doable with the list.removeItem somehow. But what if another component changes the order of the tree?

The way I would do this (not tried yet)is to write a list method which is called by the component that edits the dataset and which calls list.removeItemAt(0) until the list is empty and then recreates all the items fresh from the tree.

Would be nice to know, if there is another way. But probably not. I created the items manually, so I have to remove/refresh them manually ;-)

Anyway, thanks to provide me with the input to go further.

Markus

mericson
10-17-2004, 10:25 AM
Hmm... this does sound like an interesting challenge.

However, I think you are beginning to work against the databinding here. It is natural if the node-hierarchy parallels the view-hierarchy to have the data-binding automatically update. Then the parent/child relationships will allow the updates to happen naturally.

Your scenario involves creating different hierarchies. Perhaps another approach would be to transform your hierarchical dataset into a flattened one that will match the view hierarchy?

jocsch
10-17-2004, 11:12 AM
I think you are right. To flatten the hierarchy on the server side seems to be a lot easier than doing this.
So I will do it the "easy way" ;-)