cancel
Showing results for 
Search instead for 
Did you mean: 

remove table row

Former Member
0 Kudos

Hi,

I have a table that is coming from a R/3 display_bapi. Users can change the contents of the table and send it back to R/3 via a change_bapi.

What I want to do is remove all of the rows of the table that haven't actually been changed by the user so that a smaller amount of data is being sent. (eg. if a user has a table with 1000 rows of data (because they performed a wide search query) but only changes 1, 999 other rows should be removed from the table before RFC is executed).

How would one go about this? could I loop around the LeadSelection and isMultiSelected properties? Or must I create a flag column to the table to track "if selected" or "if changed" (or create an array). Or would it be better to copy the contents to another context element and compare the contents to determine which were changed, then delete the unchanged?

And once I find a way to determine the rows to be deleted how do I detele them?

eg.

wdContext.nodeXXX.something.something.removeSomethingAt(i);

Thanks for the help! Full points will be awarded!

Cheers,

faB

Accepted Solutions (0)

Answers (4)

Answers (4)

Former Member
0 Kudos

Hi,

Cant understand the following lines.

The problem is that all of rows changed in this way are removed by the isChangedByClient=false check. I have tried using the generic isChanged, but then it deletes all rows, even the one "changedByClient

Just elobarate it. Maybe we could it find a solution then.:)

Regards

Bharathwaj

Former Member
0 Kudos

hi ,

Just try i++ instead of ++i in the for loop.

Regards

Bharathwaj

Former Member
0 Kudos

hi,

it works now with the backwards loop. Just one thing further. Some of the fields are not changed from directly editing the table contents (changedByClient). They are copied from another table when a user performs another task. Data is changed (from another view) in a statement like:

wdContext.nodeEt_Yxxx().getEt_YxxxElementA(

.setYpr0_Kbetr(wdContext

.currentContextElement()

.getEnteredNumber());

The problem is that all of rows changed in this way are removed by the isChangedByClient=false check. I have tried using the generic isChanged, but then it deletes all rows, even the one "changedByClient".

Any final suggestions from the gurus here before I hand out the hard earned points?!

Thanks,

faB

Former Member
0 Kudos

Well, API documentation clearly states that:

1. changedByClient is set only as result of user interaction, i.e. some data comes from WD client (browser) and updates node elements at server. If you alter your elements from code this flag is not set.

2. isChanged is set whenever element changed.

VS

Former Member
0 Kudos

It is clear that changedByClient is only reflecting "changes made by the user". Basically what I want to do is:

if (isChangedByClient=false || isChanged=false) {

remove table row

}

The problem I am facing is that isChanged seems to always evaluate as false, even when I have copied new values in those context elements.

In a previous step, I copy values into the element like this:

wdContext.nodeEt_Yxxx().getEt_YxxxElementAt(i).setSomeField(wdContext.currentContextElement().getEnteredNumber());

when when the user "saves" I wan't to remove unchanged rows,but then this IF doesn't evaluate properly, it simply deletes all rows.

for (int i = listSize - 1; i >= 0; i--) {

if (wdContext.nodeEt_Yxxx().getEt_YxxxElementAt(i).isChanged(i) == false) {

wdContext.nodeEt_Yxxx().removeElement(wdContext.nodeEt_Yxxx().getElementAt(i));

}

}

Any ideas?

Thanks,

faB

Former Member
0 Kudos

Is this a plain value node or model node (with smth. like Adaptive RFC model object inside)?

VS

Former Member
0 Kudos

model node

Former Member
0 Kudos

If this is Adaptive RFC (possibly works for other) try to cast model object to com.sap.tc.cmi.util.ICMIModificationCount. If succeded do the following:

1. Save modCount value (per element) before user get input form

2. Verify modCount before save -- if values are not equals, then there are were updates.

VS

P.S. However, I still wondering why isChanged not working -- documentation clearly states that corresponding flag should be set (there should be a call to IWDNodeElement.changed(attr) in generated code for context node element.

Former Member
0 Kudos

Hi Valery,

Thanks for your input. Could you perhaps show precisely how to cast the model object?

much appreciated.

regards,

faB

Former Member
0 Kudos

if it is Adaptive RFC model then cast itself not necessary, i.e. you may use directly nodeEl.modelObject().modificationCount();

Otherwise try


final ICMIModificationCount mc = (ICMIModificationCount)nodeEl.modelObject();

VS

Former Member
0 Kudos

Hi Guys,

You're advice has been very helpful and you will get full points for your help. However, I think my newbie java skills are insufficient to get it to work. Please help me see this through.

I have scrapped the idea of changedByClient (for now, even thought it worked great!) and model casting and will just focus now on isChanged, because as you said it should work.

It really doesn't get more simple than this.

I have two views: 1 (viewA) with a table and another one (viewB) that can change multiple lines of the table at a time. both views have identical model nodes that are mapped to a controller context model node.

A user selects some rows in viewA and fills in some data in viewB and hits "update". in ViewB this kind of code is run:

for (int i = 0; i < listSize; ++i) {

if (wdContext.nodeEt_Yxxx().isMultiSelected(i) == true || leadSelection == i) {

wdContext.nodeEt_Yxxx().getEt_YxxxElementAt(i).setYpr0_Kbetr(wdContext.currentContextElement().getEnteredNumber());

}

}

then in ViewA this code is run (before executing the RFC):

//determine number rows

int listSize = wdContext.nodeEt_Yxxx().size();

//loop around the list and delete all rows that are not marked as changed.

for (int i = listSize - 1; i >= 0; i--) {

if (wdContext.nodeEt_Yxxx().getEt_YxxxElementAt(i).isChanged() == false) {

wdContext.nodeEt_Yxxx().removeElement(wdContext.nodeEt_Yxxx().getElementAt(i));

}

}

The problem is that I cannot get the the statement

wdContext.nodeEt_Yxxx().getEt_YxxxElementAt(i).isChanged() == false

to evaluate. isChanaged is never flagged!

Can I somehow manually flag the row/element when I do the copy?

Suggestions highly appreciated.

Many thanks and kind regards,

faB

p.s. I could add an extra column in the bapi table in R/3 so that I could manually use it in my webdynpro to flag and track changes, but that seems just plain silly..

Former Member
0 Kudos

I mentioned the method already:

IWDNodeElement.changed(attributeName)

This mark attribute (and whole element) as changed.

VS

Former Member
0 Kudos

Hi,

Try this.

for(int i = 0;i<nodesize;i++)

{

if(wdContext.nodeTest().getElementAt(i).isChangedByClient() == true)

{

wdContext.nodeTest().removeElement(wdContext.nodeTest().getElementAt(i));

}

}

Regards

Bharathwaj

Former Member
0 Kudos

Thanks Bharathwaj,

It seems I'm on the right track. I implemented the code and it works,but in the case where 2 rows exist and I change the first. Every other time I get an indexOutOfBounds Exception on the 'removeElement' line. It seems to depends on factors such as number of rows rows exist in the table, which row is changed (first, last, other).

I'm sure I am just looping incorrectly, or something simple like that, but I can't seem to find the error!

Again thanks,

faB

//check to see if the row was changed by the user

//if not delete it.

int listSize = wdContext.nodeEt_Yxxx().size();

for (int i = 0; i < listSize; ++i) {

if (wdContext.nodeEt_Yxxx().getElementAt(i)

.isChangedByClient() == true) {

wdContext.nodeEt_Yxxx().removeElement(

wdContext.nodeEt_Yxxx().getElementAt(i));

}

}

Error stacktrace:

java.lang.IndexOutOfBoundsException: Index: 2, Size: 1

at java.util.ArrayList.RangeCheck(ArrayList.java:507)

at java.util.ArrayList.get(ArrayList.java:324)

at com.sap.aii.proxy.framework.core.JcoBaseList.get(JcoBaseList.java:268)

at com.sap.aii.proxy.framework.core.AbstractList.get(AbstractList.java:230)

at com.sap.tc.webdynpro.modelimpl.dynamicrfc.DynamicRFCList.get(DynamicRFCList.java:281)

at com.sap.tc.webdynpro.progmodel.context.Node$ModelElementList.getElement(Node.java:2600)

at com.sap.tc.webdynpro.progmodel.context.Node$MappedElementList.getElement(Node.java:2450)

at com.sap.tc.webdynpro.progmodel.context.Node.getElementAtInternal(Node.java:672)

at com.sap.tc.webdynpro.progmodel.context.Node.getElementAt(Node.java:679)

at com.sappi.crm.pricemaintenance.ResultView.stripAndExecuteSave(ResultView.java:151)

at com.sappi.crm.pricemaintenance.ResultView.onActionUpdatePrices(ResultView.java:277)

at com.sappi.crm.pricemaintenance.wdp.InternalResultView.wdInvokeEventHandler(InternalResultView.java:416)

at com.sap.tc.webdynpro.progmodel.generation.DelegatingView.invokeEventHandler(DelegatingView.java:87)

at com.sap.tc.webdynpro.progmodel.controller.Action.fire(Action.java:67)

at com.sap.tc.webdynpro.clientserver.task.WebDynproMainTask.handleAction(WebDynproMainTask.java:101)

at com.sap.tc.webdynpro.clientserver.task.WebDynproMainTask.handleActionEvent(WebDynproMainTask.java:304)

at com.sap.tc.webdynpro.clientserver.task.WebDynproMainTask.execute(WebDynproMainTask.java:649)

at com.sap.tc.webdynpro.clientserver.cal.AbstractClient.executeTasks(AbstractClient.java:59)

at com.sap.tc.webdynpro.clientserver.cal.ClientManager.doProcessing(ClientManager.java:252)

at com.sap.tc.webdynpro.serverimpl.defaultimpl.DispatcherServlet.doWebDynproProcessing(DispatcherServlet.java:154)

at com.sap.tc.webdynpro.serverimpl.defaultimpl.DispatcherServlet.doContent(DispatcherServlet.java:116)

at com.sap.tc.webdynpro.serverimpl.defaultimpl.DispatcherServlet.doPost(DispatcherServlet.java:55)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)

at com.sap.engine.services.servlets_jsp.server.HttpHandlerImpl.runServlet(HttpHandlerImpl.java:392)

at com.sap.engine.services.servlets_jsp.server.HttpHandlerImpl.handleRequest(HttpHandlerImpl.java:266)

at com.sap.engine.services.httpserver.server.RequestAnalizer.startServlet(RequestAnalizer.java:345)

at com.sap.engine.services.httpserver.server.RequestAnalizer.startServlet(RequestAnalizer.java:323)

at com.sap.engine.services.httpserver.server.RequestAnalizer.invokeWebContainer(RequestAnalizer.java:865)

at com.sap.engine.services.httpserver.server.RequestAnalizer.handle(RequestAnalizer.java:240)

at com.sap.engine.services.httpserver.server.Client.handle(Client.java:92)

at com.sap.engine.services.httpserver.server.Processor.request(Processor.java:148)

at com.sap.engine.core.service630.context.cluster.session.ApplicationSessionMessageListener.process(ApplicationSessionMessageListener.java:37)

at com.sap.engine.core.cluster.impl6.session.UnorderedChannel$MessageRunner.run(UnorderedChannel.java:71)

at com.sap.engine.core.thread.impl3.ActionObject.run(ActionObject.java:37)

at java.security.AccessController.doPrivileged(Native Method)

at com.sap.engine.core.thread.impl3.SingleThread.execute(SingleThread.java:95)

at com.sap.engine.core.thread.impl3.SingleThread.run(SingleThread.java:159)

Former Member
0 Kudos

You must loop backwards (i = n-1, ..., 0) to avoid the IndexOutOfBoundsException.

Armin

Former Member
0 Kudos

One idea is to store all the LeadSelections (when clicked on the row)in some Storage Util like Array, and later, Save only these records.