cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Want the oppurtunity to discuss enhancements to PTC products? Join a working group! X

I would like one button to add rows to a grid widget and another button to remove rows, not sure how to accomplish this

yevans
4-Participant

I would like one button to add rows to a grid widget and another button to remove rows, not sure how to accomplish this

I have two grid widgets on my screen, and I have successfully configured a button to call a service that adds any selected rows from grid # 1 to grid # 2 using Resources["InfoTableFunctions"].Union between two infotable inputs - one being the selected rows data from grid # 1 and the other being the editedtable all data of grid # 2. The output infotable from that service is bound to grid # 2.

2016-06-21_7-57-34.png

I wanted another button that would remove rows from grid # 2 if they checked an editable checkbox in the rows. I wrote another service that can iterate the rows and remove any that have the checkbox checked, but I can't bind the output of THAT service to grid # 2 since it is already bound to the output of the first service.

2016-06-21_7-57-34.png

Any suggestions?

1 ACCEPTED SOLUTION

Accepted Solutions
qngo
5-Regular Member
(To:yevans)

I had this kind of situation several times when I want to bind many sources of data to the widget. In your case, here's what I can think about:

- Create a Thing like Helper.Mashup which contains a String property "SOURCE_DATA"

- Create a service somewhere which has 2 inputs Infotable "dataInclude" and "dataRemove" with the same DataShape as the one of data result (for grid #2). This service returns also an Infotable of the same DataShape.

- Bind 2 results All Data of the 2 services IncludeFile and RemoveFiles to the 2 inputs of the service above. Bind the result to the grid #2

- In your service IncludeFile, add: Things[Helper.Mashup].SOURCE_DATA = "INCLUDE"

- In your service RemoveFile, add: hings[Helper.Mashup].SOURCE_DATA = "REMOVE"

Now you can imagine that I try to use the property SOURCE_DATA to identify where is the data come from in order to return it to the grid #2. So, some more steps:

- In the new service, add a check: if (Things[Helper.Mashup].SOURCE_DATA = "INCLUDE") {var result = dataInclude} else {var result = dataRemove}

- Bind two events ServiceInvoked of two services IncludeFile and RemoveFile to this new service.

What do you think about this work-around ?

View solution in original post

13 REPLIES 13
nkhose
1-Newbie
(To:yevans)

Hi

I think following scenarios will work i guess

A) Your First Grid should have one service LoadFirstGridContent on mashup load

B) Your Second Grid should have one service LoadSecondGridContent service for iterating the first grid content on mashup load

C) Clicking on ADD Button will call service which will Add content on GridFirst to GridSecond ... After this service is completed (serviceinvokecompleted event) bind to LoadSecondGridContent service so as to newly load content from First Grid

D) Clicking on Remove Button & checked Rows of grid will call separate service which will remove the checked rows .... After this service is completed (serviceinvokecompleted event) bind to LoadSecondGridContent service so as to newly load content

yevans
4-Participant
(To:nkhose)

Thanks for the suggestion. I think it matters that the first grid is populated on demand from another service executing a search using a search term the user has entered, so i cannot use "on mashup load", I have to wait for the user to search for something. Then, they review the search results and pick and choose which files to select from grid # 1 and add to grid # 2. But I need to provide the functionality for them to remove a row in grid # 2 if they change their mind or accidentally select a wrong file from grid # 1.

In item C), which service do you mean "Clicking ADD button will call service"? A third service?

I can have the ​serviceinvokedcompleted​ event trigger the service that updated grid # 2 but it needs an input, and I then run into the same problem, I can't have two different service outputs bound to that same input.

Any other ideas?

nkhose
1-Newbie
(To:yevans)

In this case

A) SearchFiles Service bind to the first grid and when SearchFiles Serviceisinvoke complted you then bind other service

i.e to load the second grid call service say LoadSecondGridcontentonsearch (At this point both grid will have contents on basis of serach)

B) Now user will select row from Grid 1 and click "ADDFILES" button here we bind service say ADDContent having param as selected Row from grid 100

C) When  ADDContent service is completed we will call the same service from (A)  LoadSecondGridcontentonsearch which will load newly content added in (B)

(D)Now to remove row from grid # 2 say we have service say REMOVERow , so when user clicks on Remove Button it will call this service REMOVERow

   having param as selectedrow from grid # 2 , when REMOVERow service is serviceinvoke completed call the service LoadSecondGridcontentonsearch in (A)

   based on search term by user

 

  ### As long as user selects grid # 1 row and try to hit RemoveRow button we need to provide a validator widget and show status message on that

   or simply show/hide (visible property of button (bool) - use expression widget)RemoveRowButton only when user selects row from Grid # 2 or check the checkbox from grid # 2

yevans
4-Participant
(To:nkhose)

I am a little unclear, what is the input parameter(s) for LoadSecondGridcontentonsearch in your example?

nkhose
1-Newbie
(To:yevans)

The service  LoadSecondGridcontentonsearch is for grid # 2 .... as per your reply the input will search term , as long there is search term , this service will

iterate over the newly added content (Files in this case) from (B)

I have tried my best to explain this pictorially it will be too long , hope this helps

yevans
4-Participant
(To:yevans)

Thanks Nilesh for your proposed solution but it does not help.

Can anyone else think of a way to accomplish my goal of being able to update one table with two services (since the table can only be bound to the output of one server)?

Thanks

qngo
5-Regular Member
(To:yevans)

I had this kind of situation several times when I want to bind many sources of data to the widget. In your case, here's what I can think about:

- Create a Thing like Helper.Mashup which contains a String property "SOURCE_DATA"

- Create a service somewhere which has 2 inputs Infotable "dataInclude" and "dataRemove" with the same DataShape as the one of data result (for grid #2). This service returns also an Infotable of the same DataShape.

- Bind 2 results All Data of the 2 services IncludeFile and RemoveFiles to the 2 inputs of the service above. Bind the result to the grid #2

- In your service IncludeFile, add: Things[Helper.Mashup].SOURCE_DATA = "INCLUDE"

- In your service RemoveFile, add: hings[Helper.Mashup].SOURCE_DATA = "REMOVE"

Now you can imagine that I try to use the property SOURCE_DATA to identify where is the data come from in order to return it to the grid #2. So, some more steps:

- In the new service, add a check: if (Things[Helper.Mashup].SOURCE_DATA = "INCLUDE") {var result = dataInclude} else {var result = dataRemove}

- Bind two events ServiceInvoked of two services IncludeFile and RemoveFile to this new service.

What do you think about this work-around ?

yevans
4-Participant
(To:qngo)

Yes, that works very well! I was trying to go down a similar path - if you use pure JS in a web app and define a click event on an HTML element like a button, in the function called by the event you could query the source of the event with something like event.target.id to determine which button was pushed. I could not figure out how to do that in a mashup, so your solution basically achieves the same effect.

I just defined a variable as a property on the thing where all my services are - so I basically have three services:

includeFile:

me.sourceData = "include";

removeFile:

me.sourceData = "remove";

updateTable:

if (me.sourceData === "include) {

  <add selected rows of grid # 1 to grid # 2>

} else if (me.sourceData === "remove") {

  <remove checked rows from grid # 2>

}

I only need to bind the two tables as inputs to the third service, the first two services have no inputs or outputs. I just bound the serviceInvokeCompleted event for both of them to the third service.

Thanks for your help, I've been trying to figure this out for a week!

Yale

qngo
5-Regular Member
(To:yevans)

You're welcome. Good to know that could help!

Quang-Dung

wposner-2
12-Amethyst
(To:qngo)

This works as long as multiple people don't click two different actions at the exact same time since the "SOURCE_DATA" property value on the Thing is global. 

The best way to do this is use a session variable, defined as the same datashape as your display widget, which you programmatically set after every add, update, delete.  Then use a getter service which gets the value of the session variable.  You bind the "All Data" from the results of your getter service to your display widget (since they're both of the same datashape) and bind the "ServiceInvokeComplete" event of add, update, and delete services to the getter service for your session variable.  

This is a pseudo MVC implementation where the session variable is acting as your model.

yevans
4-Participant
(To:wposner-2)

Ah yes, I hadn't thought of that possible conflict. The possibility of it ever happening would be extremely low, since the time it takes between the first service that updates the global property and the second service that reads it upon ServiceInvokeCompleted is milliseconds. But if I did want to try your option to prevent that from even being a possibility, please let me makes sure I am understanding correctly, as I have not used session variables yet:

I assume you are referring to "Session ​Parameters​"? (as defined in the help docs) So I would create a new thing with the same data shape as my table (or would it be a thing ​template​?), add it as a session parameter in the session tab, and update it using different services bound to my different buttons, then update my display widget on the ServiceInvokeCompletion of those services? How to I reference the session parameter thing(?) in that service's JS? Is the session parameter thing(?) like an session-specific instantiation of a thing/thing template? It's confusing in the docs, as they say, "Session Parameters are global session specific parameters that can be used on the Client and Server side." why does it say they are global?

Thanks!

Yale

wposner-2
12-Amethyst
(To:yevans)

You need to create a thing shape with an infotable property that is the same data shape as your grid.  Add your TS in the user management subsystem per the docs and any parameters you create on that TS, will be available as a session parameter.

To read your session parameter you use the following:

var data=Resources["CurrentSessionInfo"].GetGlobalSessionValues().protocolConnections;

where, in this case, "protocolConnections" is the name of my parameter defined on my TS.

To save your changes to your session parameter you would use the following:

var params = {

name: "protocolConnections" /* STRING */,

value: protocolConnections /* INFOTABLE */

};

Resources["CurrentSessionInfo"].SetGlobalSessionInfoTableValue(params);

where the name attribute is the name of your session parameter and the value attribute is the infotable containing your data.

Finally, you will always access your session variable through the getter service which simply returns an infotable of the same data shape with following code:

var result=Resources["CurrentSessionInfo"].GetGlobalSessionValues().protocolConnections;

So create your add, update, delete services and bind the click events to your different buttons.  The only thing you need to pass to update and delete services are the selected item(s) from your getter service.  For the add functionality, you'll obviously need to pass the data you're trying to add.  Your add, update, delete, services will manipulate the session parameter using the code above to retrieve the data stored in session and then save it back.  Once your add, update, delete services complete, call your getter service and use the result to bind to your grid. 

The session parameters are global in that whatever data you have stored in any given session parameter is globally available within that current session.  All the data will stay in that parameter until the session expires or the user logs out.  You need to make sure that you clear your session parameter with a new instance of it's infotable (Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params);)  if you need use the same session parameter for different data.

Thanks for the work around. i used it for two buttons, one adding one day and the other retrieving one day, and the result of the two services associated with the buttons goes to a datetime picker trouhg a custom service called MyService wich is based on the source property of the thing,

Capture.PNG

Capture.PNG

Capture.PNG

Top Tags