PDA

View Full Version : how to delete rows in a grid


thriputapriya
05-17-2006, 12:50 AM
Hello,

I want delete multiple rows in a grid by clicking delete button.How do i do this in laszlo.Could you provide is there any method for this.

Thanks in advance,
Rudresh

aaronjudd
05-18-2006, 12:42 AM
I do something like this


<button>
<method name="doClick" event="onclick">
<![CDATA[

// Delete Mulitple Results
dp = new LzDatapointer();
arrayDatapointers = top.xpathQuery('sResults:/node');
for (i=0;i< arrayDatapointers.length;i++) {
dp.setPointer(arrayDatapointers[i]);
dp.deleteNode();
}

]]>
</method>
</button>


You can also set the arrayDataPointers with :

arrayDatapointers = obj.getSelection();


Hope that helps.

thriputapriya
05-18-2006, 01:26 AM
Thank you aaronjudd,for your reply.

Yeah.. i can delete the xml nodes.But in my application i want updated the database for respective deleted value. For that i want know which row i have deleted in grid and also i should delete same data in of that row in DB table. Do you have any idea for this problem.

Thanks in advance,
Regards,
Rudresh

aaronjudd
05-18-2006, 02:02 AM
I am writing code for this in a few days, but here's what I am thinking:

Are you connecting to an update/delete script?
Do you already have code to delete/update just one item?
You could loop through (as above) and just run the delete method for each time (passing it a key from your node data).. that's fine for just a few rows.

Otherwise I might pass all the xml nodes to the delete script and parse them into a single delete sql statement.

I am planning on just writing code to handle them one at a time (in the loop) because the most I see my app deleting is hmm, 10 records at time.

What language are using for your delete/update scripts?

Azza
05-18-2006, 04:04 PM
We have templated CRUD operations by having delegates that handle each operation. We use a dataset that sits behind the table, and as we upate elements in the table the dataset is also updated. We have a save button which then calls the update delegate to build up a method call to a soap service using the updated values in the dataset. For create, we use the concept of new: dataset, simalarly to the example in the developer documentation. The create delegate agian builds the method call using the new values. For delete, an Id has to be passed back to the service. This works well for a model that can be serialised easily, without complex relationships.

Our service classes extend soap, adding the functionality to take a DTO (name value pairs) as a parameter to use to build up the method call. We also have the ability of registering delegates to events in the service to push the handling of data/errors into a controlling template.

I have attached a template.

Cheeers,

Aaron.

<library>

<class name="mytemplate">

<datapointer name="dp"/>

<method event="oninit">
<![CDATA[
// Load all MyData into dsMyData on load of myService
this.loadMyDataDel = new LzDelegate(this, 'loadMyData');
canvas.myService.registerDelegate(this.loadMyDataD el, 'onload');

this.createDel = new LzDelegate(this, 'handleCreateSuccess');
this.updateDel = new LzDelegate(this, 'handleUpdateSuccess');
this.deleteDel = new LzDelegate(this, 'handleDeleteSuccess');
this.errorDel = new LzDelegate(this, 'handleError');

]]>
</method>

<method name="handleCreateSuccess">
Debug.write('Successful create');
canvas.myService.unregisterDelegate(this.createDel , 'ondata');
this.loadMyData();
</method>

<method name="handleUpdateSuccess">
Debug.write('Successful update');
canvas.myService.unregisterDelegate(this.updateDel , 'ondata');
this.loadMyData();
</method>

<method name="handleDeleteSuccess">
Debug.write('Successful delete');
canvas.myService.unregisterDelegate(this.deleteDel , 'ondata');
this.loadMyData();
</method>

<method name="handleError" event="onerror" args="error">
Debug.write('Error! ' + error);
Debug.write('Message: ' + error.message);
Debug.write('Info: ' + error.info);
</method>

<method name="loadMyData">
<![CDATA[
Debug.write('Loading all MyData');
canvas.myService.queryAllMyData();
Debug.write(canvas.datasets.dsMyData.serialize());
]]>
</method>

<method name="addNewRecord">
<![CDATA[
var dp= this.editableRow.datapath;
Debug.write('Add new Record');
Debug.write(dp.serialize());

this.myData.setAValue(dp.xpathQuery('@avalue'));

canvas.myService.invokeCreate(this.myData, this.createDel, this.errorDel);
]]>
</method>

<method name="updateRecord" args="dp">
<![CDATA[

Debug.write('Update Record');
Debug.write(dp.serialize());

this.myData.setAValue(dp.xpathQuery('@aValue'));
canvas.myService.invokeUpdate(this.myData, this.updateDel, this.errorDel);
]]>
</method>

<method name="deleteRecord" args="myId">
<![CDATA[
Debug.write('Delete Record');
this.myData.setMyId(myId);
canvas.myService.invokeDelete(this.myData, this.deleteDel, this.errorDel);
]]>
</method>



<myData name="myData"/>
<!-- This view is simply used to hold the column widths for the myData table -->
<view id="myview" visible="false">
<attribute name="widthAValue" value="90" type="number"/>
</view>

<simplelayout axis="y" spacing="5"/>


<view name="editableRow" datapath="new:/myData/">
<cell><edittext datapath="@aValue"/></cell>
<cell>
<button text="Add Record">
<method event="onclick">
classroot.addNewRecord();
</method>
</button>
</cell>
</view>
<view height="1"/>
<table name="table">
<simplelayout axis="y" spacing="1"/>
<attribute name="nextColor" value="0xEEF0EB" type="string"/>
<view name="row">
<datapath xpath="myData" sortpath="${parent.parent.sortOrder}" sortorder="ascending"/>
<method event="ondata">
var nextColor = this.parent.getAttribute('nextColor');
this.readonly.setAttribute('bgcolor', nextColor);
this.setAttribute('bgcolor', nextColor);

if (nextColor == '0xFFFFFF') {
this.parent.setAttribute('nextColor', '0xEEF0EB');
} else {
this.parent.setAttribute('nextColor', '0xFFFFFF');
}
</method>
<view name="readonly">
<simplelayout axis="x" spacing="2"/>
<cell><datapath="@avalue"/></cell>
<cell>
<simplelayout axis="x" spacing="2"/>
<button text="Edit">
<method event="onclick">
this.parent.parent.parent.editable.setAttribute('v isible', true);
this.parent.parent.setAttribute('visible', false);
</method>
</button>
<button text="Delete">
<method event="onclick">
var myId = parent.parent.parent.datapath.xpathQuery('@myId');
classroot.deleteRecord(myId);
</method>
</button>
</cell>
</view>
<view name="editable" visible="false">
<simplelayout axis="x" spacing="2"/>
<cell><edittext datapath="@avalue"/></cell>
<cell>
<simplelayout axis="x" spacing="2"/>
<button text="Save">
<method event="onclick">
parent.parent.parent.datapath.updateData();
classroot.updateRecord(parent.parent.parent.datapa th);
this.parent.parent.parent.readonly.setAttribute('v isible', true);
this.parent.parent.setAttribute('visible', false);
</method>
</button>
<button text="Cancel">
<method event="onclick">
this.parent.parent.parent.readonly.setAttribute('v isible', true);
this.parent.parent.setAttribute('visible', false);
</method>
</button>
</cell>
</view>
</view>
</table>
</class>

</library>

dsalama
05-19-2006, 04:56 AM
Aaron,

Very interesting approach. I know it may not be relevant to this topic, but, would you mind posting the contents of myService? I'm still learning OL and I appreciate every bit of code I see out there. And understanding databinding has been the most difficult to me yet. I understand the goal of your mytemplate class, but I'd like to really understand the behind the scenes.

Thanks,
Daniel

Azza
05-21-2006, 05:34 PM
Unfortunately IP prevents me from doing so... Im border line posting the template ;) Maybe with some consulting fees if your interested!

dsalama
05-21-2006, 06:13 PM
That will be fine. I was just curious for learning purposes. If IP and you wouldn't mind, it will suffice to just explain what myService does from a high level PoV.

Thanks again,
Daniel

Azza
05-21-2006, 07:18 PM
Client side:
Our service classes extend soap, adding the functionality to take a DTO (name value pairs) as a parameter to use to build up the method call. We also have the ability of registering delegates to events in the service to push the handling of data/errors into a controlling template.

Server side:
We use document-wrapped style soap messages. We use xfire to expose remote methods, its a great tool that can be injected by spring. We use hibernate to persist our domain model. We create fine grained remote methods that are exposed as soap, and create/populate domain objects similar to a controller/struts action. We then have an internal service layer that deals with domain objects as method parameters.


Cheers,

Aaron.

dsalama
05-29-2006, 07:57 AM
Aaron,

Thanks again for the explanation. I'm mostly interested in the client side of your approach in trying to understand sort of like best practices on using laszlo.

If you don't mind answering some of my concerns, I'd really appreciate it. They are not specific to your code or your application (I think).

Anyway, my curiosity concentrates on the fact that you use delegates so much for basically all CRUD actions. I have a "simple" app that currently provides the user with a search form and upon "submitting" the form, it updates the querystring of a dataset and sends the doRequest method. The response from the server could be one of:

<response>
<success>
<... actual data ...>
</success>
</response>

or

<response>
<errors>
<... error messages ...>
</errors>
</response>

Then I have a view that contains two "elements". One is a view whose datapath is bound to "/response/errors" so it will show the error messages, if any. The second element is a grid whose datapath is bound to "/response/success" which gets populated with data when there are no errors.

When I submit the search form with criteria that returns /response/success, the grid works just fine, and I can repeat the process by changing form value criterias and it works just fine.

However, when I search for a criteria that I know will return /response/errors, the error messages show up as expected and not the grid. However, at that moment, the application is "frozen"/stuck. Meaning, I cannot click on any buttons, menus, drag windows, nothing. I could type into the seach form text elements but I cannot submit anything.

I think it has something to do with the grid and the fact that it had information before and not anymore.

I wrapped the view that encloses the two "subviews" (error messages and grid) in a state that gets destroyed and applied every time the form is submitted and that seems to have corrected the problem.

Well, after all this long explanation... where am I going with it? I'm not necessarily asking for your help in solving this problem. I'm just curious to see if I used delegates ir would me more efficient, scaleable, elegant, etc. Since your "framework" seems to use delegates extensively, I'm just wondering if you have any suggestions to give me.

Maybe your suggestions won't solve my problem but I'm sure they will help me develop better and more elegant laszlo apps.

Thanks,
Daniel

Azza
05-29-2006, 04:24 PM
The main reason that we decided to design the client side classes to use delegates is for flexibility. In the case that you recieve an error and want to do more than just display the message to the user, you have the ability to register a method to handle the onerror event, and programmatically deal with the error in the client side. We do have something similar to what you mentioned in that the response from a remote method is bound to a dataset, but that is only in the case of a successful response. What are you using for databinding? Are you distinguishing between data and error events? If you are, I would override the methods that handle the ondata and onerror events in your grid and/or dao classes and add Debug statements as to what was recieved in the response. This might give you a good indication of why the application is frozen.

<grid name="myGrid>
<method event="ondata" args="data"
Debug.write('Recieved :' + data);
...
</method>
</grid>

I hope this helps.

Cheers,

Aaron.

dsalama
05-29-2006, 04:28 PM
Aaron,

Thanks for the response. I understand your PoV in using the datasets. It's a good approach and I'll start using it.

I rewrote the app from scratch eliminating all custom made classes and just making a simple view in the canvas to hold my search form and the response. It turns out that everything works fine now. It must be something I'm doing in my custom made classes or something. I'll start refactoring my app back into classes and see how it works. Then I'll start using delegates.

Thanks again,
Daniel