PDA

View Full Version : Problem updating certain kinds of datasets...


rbrown3
11-03-2004, 02:34 PM
Greetings:

I have run into an interesting problem with the use and updating of various datasets.

I have some (somewhat) heirarchical data that I would like to manage:

<dataset name="userlist">
<users>
<user>
<firstname>Reed</firstname>
<lastname>Richards</lastname>
<id>3085</id>
</user>
<user>
<firstname>Susan</firstname>
<lastname>Richards</lastname>
<id>3083</id>
</user>
<users>
<dataset>

I have a nice grid which displays the contents of this dataset, and a form which I am trying to use to add "user" nodes to this dataset. Unfortunately, I am having problems doing the add.

My form sets the datapath to "new:/user" (in accordance with the instructions in Chapter 30 of the developer's guide), and I have several edittext tags that receive data for the new "user" node. An example of one of these tags is below:

<edittext name="firstName" datapath="$path{'firstname/text()'}" />

The chapters on datapointers and datasets are somewhat vague, but based on what I've seen in Chapter 29 the "node" indicated by a $path statement should be updatable using the updateData() method.

Unfortunately, it appears that $path only works with attributes. When I attempt to add a node whose "firstname" tag is set using the above syntax, I get blank names and ids in my list.

More unfortunate: I notice that all of the data binding examples given in the documentation-- especially the excellent example in Chapter 30 that involves creating new nodes and updates -- all seem to use attributes. In other words, adding new nodes and updting existing ones is easy when you have data like the following:

<user firstname="Reed" lastname="Richards" id="3085" />

In the above case, the binding is easy. Just create an edittext like the one below:

<edittext name="firstName" datapath="@firstname" />

But suppose someone doesn't want to structure their data that way???

My question is this: in order to bind data so that you can be able to add nodes or change them, does the data to be added always have to be attributes? Or is there a way to add or change data structured like <firstname>Reed</firstname> so that I can add or change something like <firstname>Joseph<firstname>?

If there is a way to do this, will someone please enlighten me on the proper syntax to use in order to do so???

Thanks in advance...

ZiQuiLLa
11-09-2004, 01:02 PM
Hi, I have the same problem, the examples are only for attributes, you solved the problem?

nevin
12-02-2004, 01:14 AM
I've face this problem too! Does anyone from Laszlo can answer the question?

When using a node in the xml instead of an attribute. The edittext field simply disappear!

Can the "new:/something" works with nested xml?

Update:
I found that this can works if you programmatically create the whole XML structure and set the datapath for each input field afterward.


<method event="ondata"><![CDATA[
if ((parent.mode == "new") && (this.datapath.getNodeCount() == 0)) {
this.datapath.addNode("code", "");
this.datapath.addNode("description", "");
this.datapath.addNode("cost", "0.0"); this.code.field.setDatapath("code/text()");
this.desc.field.setDatapath("description/text()");
this.cost.field.setDatapath("cost/text()");
]]></method>

rbrown3
12-03-2004, 05:25 AM
nevin & ZiQuiLLa:

Actually, I did find a viable solution to the problem, though the process of doing so was somewhat painful. It is similar in some ways to what nevin did.

Before outlining what I found, I would like to express my profound disappointment and dismay at the Laszlo people for their lack of responsiveness to this problem. By articulating this problem I have exposed a glaring hole in the Laszlo documentation. Not only wasn't this hole corrected (at least, not to my knowledge), but it appears that you people completely ignored this thread and the problem that it exposed. The reality is that there will be times when people will want to express XML data in the way that was described in the base post here. There will be times when such expression is necessary for various reasons. The fact that your documentation does not describe add and update operations that can handle things other than attributes is bad enough; that you folks did nothing to help when the problem was exposed is extremely disturbing. You had plenty of time to respond, but you didn't. The result was that a user and potential promoter of your software was put through a lot of unnecessary pain in order to solve a problem which you people, as the ones most knowledgeable about this system, could have helped resolve in a few hours. Worse, there was a point in time when I thought that there *was* no viable solution to this problem; if I had entertained that thought I would have considered your XML data handling flawed, limited, and unusable in some really important circumstances. This would have led me to conclude that your software was incomplete and I could well have dumped it and moved on to evaluate other technologies.

This, folks, is not how you convince people that your product is worthy of being the "wave of the future" in web- based GUIs. This is not how you support people who may be trying to promote the use of your software in their organizations. I sincerely hope that this kind of negligence is not a habit of yours. If it is, not only do I doubt that your goals of wide adoption of this technology will be met, but I doubt if you are really serious about meeting those goals.

Enough said (for now, at least).

Like nevin, I found that the solution to creating/saving things other than attributes is in the datapointer object. It turns out that XML data in Laszlo is handled in a manner similar to a DOM document. Once I realized this, the solution suggested itself fairly quickly: create a root node for the data that you want to add, and then add "child nodes" that contain the actual data. Once you have done this, just add your newly created data to the existing DOM tree.

In other words, taking the example data I put in the base post:

<dataset name="userlist">
<users>
<user>
<firstname>Reed</firstname>
<lastname>Richards</lastname>
<id>3085</id>
</user>
<user>
<firstname>Susan</firstname>
<lastname>Richards</lastname>
<id>3083</id>
</user>
<users>
<dataset>

and assuming I wanted to add another user to the list, I would need to put in the following:

<datapointer id="newUser" xpath="new:/user" />

This creates a datapointer that points to the root of a new "user" tree (note here that I am planning on adding a new "user" tag with user information).

I would need to create some kind of input form (dialog box, window, whatever) to receive the desired user info:

First name: Joseph
Last name: Richards
ID: 3086

I would then grab those strings from whatever input objects I used, and add each piece of information as a child of the node your datapointer points to. Pretending for a moment that the information given above is in variables called fname,lname, and uid, respectively, the adding to the node would work as follows:

<method event="onclick">

(get the variables and/or do other stuff)...

newUser.addNode("firstname",fname,null);
newUser.addNode("lastname",lname,null);
newUser.addNode("id",uid,null);

At this point, you effectively have a little DOM document containing the new information. Next you want to get a pointer to the root node of your main XML dataset:

var main=canvas.datasets.maindata.getPointer();

and then get a pointer to the root of your data (in my case, the root is represented as the "users" tag):

var chld = main.selectChild();

"users" is the parent of all "user" tags. Once you are pointing to that, you just add the new information:

main.addNodeFromPointer(newUser);

If you want to reuse the newUser pointer afterward, you can clean it out just by creating a new user node:

newUser.setXPath("new:/user");

And that is it.

This is the solution that I found. There may be others, but the nice thing about this one is that it is pretty generic. It works for everything -- including adding attributes. You just have to have an understanding of DOM (read any good XML book for that) and the methods associated with the datapointer object.

Study the methods of datapointer; they include ways to add attributes as well as text to a node.

Of course, the one unfortunate aspect of this solution is that there is apparently no binding between the text in a tag and any of the UI controls. I do consider this a flaw in the Laszlo system, because while you can bind a tag's attribute to a control there still is no apparent way to bind a tag's text to a control. Of course, with this solution you can get around that flaw, and because it is generic enough to handle just about anything you shouldn't need bindings at all.

Of course, I could also be wrong about the inability to bind text to a control; maybe the Laszlo people, if they can spare the time, could enlighten us about this.

That is the solution I found. I hope this helps people...

adam
12-03-2004, 09:58 AM
Hi.

I hope I can help here. You may find it a little less cumbersome to use the LzDataElement APIs directly, rather than relying on datapointers.

Also, there appears to be bug with new:/ datasets updating(!) I'll take a look at this and hopefully get it fixed.


In the mean time, you can create a new dataset in script and point to it. I wrote a little program (below) that hopefully covers some of this stuff. Reply here if you have any more questions.

<canvas>
<simplelayout spacing="10"/>

<view>
<simplelayout spacing="2"/>
<edittext name="a"> test a </edittext>
<edittext name="b"> test b </edittext>
<edittext name="c"> test c </edittext>
<button>Add
<method event="onclick">
var n = new LzDataElement( 'item' );

var names= { a : true , b : true , c : true };

for ( var k in names ){
var an = new LzDataElement( k );
var at = new LzDataText( parent[ k ].getText() );
an.appendChild( at );
n.appendChild( an );
}

listparent.datapath.p.appendChild( n );
</method>
</button>
</view>

<view id="listparent">

<datapath/>

<method event="oninit">
var ds = new LzDataset( );
var el = new LzDataElement( 'data' );
ds.appendChild( el );
this.datapath.setPointer( ds );
</method>

<simplelayout spacing="2"/>
<view bgcolor="#CCCCCC" datapath="*" id="xxx">
<simplelayout axis="x"/>
<text datapath="a/text()"/>
<text datapath="b/text()"/>
<text datapath="c/text()"/>
</view>
</view>
</canvas>