Getting data from Agile Platform's Web Blocks to their owners

Getting data from Agile Platform's Web Blocks to their owners

  
Justin James wrote:
Don't you just love discovering easy ways to do what you thought you couldn't?
http://www.techrepublic.com/blog/programming-and-development/getting-data-from-agile-platforms-web-blocks-to-their-owners/5578

J
.Ja
 
I knew it already, but I agree that when you found out that one you can do a lot more :-)

Kind regards,
Evert
Justin James wrote:
Don't you just love discovering easy ways to do what you thought you couldn't?
http://www.techrepublic.com/blog/programming-and-development/getting-data-from-agile-platforms-web-blocks-to-their-owners/5578

J
.Ja
 

Why not serialize a recordlist from the webblock and return the xml in the NotifyMessage, on the higher level you just deserialize the NotifyMessage back to a record list and your data from the webblock  ;-)

Only problem i have found is that this does not work for record list of structs (or combined recordlists on more then 1 entity).

regards,

Paul
Paul van Hoof wrote:
 

Why not serialize a recordlist from the webblock and return the xml in the NotifyMessage, on the higher level you just deserialize the NotifyMessage back to a record list and your data from the webblock  ;-)

Only problem i have found is that this does not work for record list of structs (or combined recordlists on more then 1 entity).

regards,

Paul
 
Sure, you can do that, but the XML serialization is poorly implemented. I have NOT been able to rely upon it, much to my dismay. Whenver I need to use XML, I either write C# or manually parse it, that's way too much work.

J.Ja
Justin James wrote:
 
Sure, you can do that, but the XML serialization is poorly implemented. I have NOT been able to rely upon it, much to my dismay. Whenver I need to use XML, I either write C# or manually parse it, that's way too much work.

J.Ja
 
 I never had problems with the XML Records extension, for that purpose. Did you try that? :)
António Chinita wrote:
 
 I never had problems with the XML Records extension, for that purpose. Did you try that? :)
 
I have been very unhappy with that extension overall, so I would not think to use it for this purpose. It takes far less effort to write to DB and comma delineate IDs than it does to mess with XML Records, and it also passes less data around too.

J.Ja
Justin James wrote:
 
I have been very unhappy with that extension overall, so I would not think to use it for this purpose. It takes far less effort to write to DB and comma delineate IDs than it does to mess with XML Records, and it also passes less data around too.

J.Ja
 
I know what you mean. It can take a while to setup indeed. If I only need to pass a single record, or a list of ids, I usually go for CSV as well. :)
However, you don't have much choice for whole (multi attribute) record lists or complex data structures, as XML serialization can take a big effort from your hands.
Hi,

Nice topic Justin.
By the way, a bit related to that is a nice trick on RichWidgets called "FakeNotifyWidget"

Did any of you ever wanted to call a screen action from javascript?
That's the way to go.

From the block description:
"Use this widget to call a screen action from JavaScript:
1. Name this widget, edit its JavaScript and add the following call: OsNotifyWidget('<WebBlockWidgetName>.Id', '<message>').
2. Use the 'NotifyWidgetGetMessage()' built-in function in the flow of the 'FakeOnNotify' screen action to get the <message> value."

Regards,
João Rosado

Justin James wrote:
 
I have been very unhappy with that extension overall, so I would not think to use it for this purpose. It takes far less effort to write to DB and comma delineate IDs than it does to mess with XML Records, and it also passes less data around too.

J.Ja
 
 
Imagine a situation where you do not yet want to write this data to the db, since the webscreen above the webblock will save (or not save) the data from the webblock related to data on that webscreen. I have found that using xml is a very quick and precise way of handling this issue.

regards, Paul
Paul van Hoof wrote:
 
 
Imagine a situation where you do not yet want to write this data to the db, since the webscreen above the webblock will save (or not save) the data from the webblock related to data on that webscreen. I have found that using xml is a very quick and precise way of handling this issue.

regards, Paul
 
Paul - That's a pretty rare edge case. :)

J.Ja
Funny enough, I have just implemented the NotifyWidget process last week. Works like a gem.

However, if you have webblocks inside webblocks, and you need to move through multiple weblocks to notify eachother, this can add 1-2 seconds per webblock notify action.

By implementing the FakeNotifyWidget process, will that solve this issue by directly notifying the intended webblock???
Any samples available?

Cheers

RN.
João Rosado wrote:
Hi,

Nice topic Justin.
By the way, a bit related to that is a nice trick on RichWidgets called "FakeNotifyWidget"

Did any of you ever wanted to call a screen action from javascript?
That's the way to go.

From the block description:
"Use this widget to call a screen action from JavaScript:
1. Name this widget, edit its JavaScript and add the following call: OsNotifyWidget('<WebBlockWidgetName>.Id', '<message>').
2. Use the 'NotifyWidgetGetMessage()' built-in function in the flow of the 'FakeOnNotify' screen action to get the <message> value."

Regards,
João Rosado
 
 
 Hello João,

Do you have any example of this? It sounds good but think it's maybe hard to get what you want (but thats maybe because I read it like that).

To call an action from another block (that in the same screen), I always do the following:
In the webblock where you want to call an action (let's say a refresh of something in that block), I set the id of the button that calls the refresh action to the session (in the preparation). In the other webblock I just use the richwidgets -> widget_click action to click on the (session) button id and then that action is called.

Kind regards,
Evert
Hi Evert,

FakeNotifyWidget is nice to call screen actions in the same block/screen from javascript where you put it.
It avoids most uses of hidden inputs/ hidden button workarounds to pass information to screen actions or just call screen actions.

To call
sibling blocks is harder because you don't know the <WebBlockWidgetName>.Id
You would have the same problem that you have with the button id.

I'll think about it and see if I can get a better solution for that case.

Regards,
João Rosado
João,

My experience with the onNotify is that all notify actions (in the same block) are 'triggerd' when doing an notify. So that would cause some overhead regarding the action you do want to execute.

THE solution for calling an action in another webblock would still be needed :-).

Kind regards,
Evert
Evert,

You have a simple solution to do that with a WebBlock which involves passing the ID of a link/button, associated with the notify action you want, as an input parameter of the WebBlock and then "click it" through javascript.

Check the example in the FlowMenu component

Cheers,
Hermínio Mira
Hello Hermínio,

That would only work when the link is in you're screen and not in another webblock on that screen. That being said, again you can have mutiple notify action in one screen which are all 'triggerd' when using the onnotify.

Even so, I don't like to send 'button id's' with an input parameter. Input parameters are easier to 'see' for the user and therefor worse for security options.

Kind regards,
Evert
I'm using this NotifyWidget action on a screen at the moment which has a web block with check boxes in it. As each checkbox is clicked or unclicked, a text message with that info is sent up via NotifyWidget to an action on the page that simply concatenates that string onto other previous string values, so it has one long string which is a list of all the clicks with the relevant IDs.

Once the user's finishing clicking all the checkboxes that apply, there's a Save button on the main page which runs through the concatenated string, separates it out into its separate parts, and either adds or deletes records according to whether the checkbox was selected or unselected.

However, each time I click on a checkbox, it makes an AJAX call which takes a second or so. If I quickly click a few checkboxes then click Save, not all the AJAX calls will have been completed, so one or more of the latest clicks will not be saved.

Here are my questions:

1 - why does it make an AJAX call to the server, rather than simply saving the concatenated string locally in the browser?
2 - is there a way to speed this up so I don't end up with a slow moving queue of requests if someone quickly does a series of different clicks?
3 - if performance can't be improved, has anyone got any other ideas on how to solve the problem of timing so I always save every item that's been clicked on?

Thanks, Iain
Iain,

I have been looking for help with your issue in question 2.
I think we are trying to do the same thing, and like you said, if the some quickly conducts a series of selections then there is a queue of requests made. 

I hope there is a way around this.

Robbie
@Iain:

I think the answer is notifying widgets is meant for AJAX and not the high-traffic swapping  you are proposing.
You need to write the javascript yourself for the things you want.
Iain Fogg wrote:
However, each time I click on a checkbox, it makes an AJAX call which takes a second or so. If I quickly click a few checkboxes then click Save, not all the AJAX calls will have been completed, so one or more of the latest clicks will not be saved.
 
 Hi Iain,

If the save button is also an Ajax it will be added to the queue, it will be delayed but at least would have the correct information.

Anyway, I agree with Joost.
Notify Widget is nice, but it can be a bit heavy with big viewstates / network delays. So it should be avoided on potentially fast operations like clicking many checkboxes.

Maybe taking another aproach to your application requirements would be a good idea.
My first reaction (not knowing your application) would be "Why aren't the checkboxes directly on the page?".


Regards,
João Rosado
Hi, thanks for the updates. I guess I need to bite the bullet and figure out how to work with Javascript in OutSystems - haven't done that one yet...

The reason the checkboxes are in webblocks is that the main page lists parent records, then the webblock attached to each parent record shows a list of related child records with the checkboxes against them. It's a pretty complex affair working out which child records to show, which is why it was encapsulated as a webblock. I couldn't work out how to have the parent and child data loaded and displayed together at the top page level (which I appreciate would have removed this issue if I could have done that).

Now to figure out the Javascript integration...
Iain Fogg wrote:
I'm using this NotifyWidget action on a screen at the moment which has a web block with check boxes in it. As each checkbox is clicked or unclicked, a text message with that info is sent up via NotifyWidget to an action on the page that simply concatenates that string onto other previous string values, so it has one long string which is a list of all the clicks with the relevant IDs.
 
 
 Hi

You can keep the same "architecture" (having that webblock with the checkboxes), but instead of using NotifyWidget, have a javascript event on the checkboxes that makes the concatenation and stores it in an hidden input created on the page. You can even pass the input ID to the webblock so it can be reused.

Say you create an Input (bound to some variable) in the main page and set its name to: InputConcatenatedCheckboxes
In the web block, you may create an Extended property:
Name 1: onchange
Value1: "SetResetCheckBox(this);"

and create the SetResetCheckBox function in the Weblock  Javascript:

function SetResetCheckBox(checkbox){
 var elem = document.getElementById("wt9_wtMainContent_wtInputConcatenatedCheckboxes");  
 if(checkbox.value=='on'){  
   //...
   elem.value = elem.value + "," + checkbox.id;
   //..
 } else {
   //...
 }
}


Thanks @avieira, that's really helpful. Just trying that now, but there's one thing I couldn't work out.

I'm passing the name of the input box from the main page into the webblock as a parameter (as you suggested), but I couldn't work out how to take that parameter in the webblock to pass it into the Javascript function. The actual function's in place, I just can't see how you interact with the OutSystems items such as parameters or variables to get values from there into the Javascript. Any chance you could give me a pointer on that?

Cheers!
(update: in the post forgot the "Escape Content")

-- In the web block:

1. Create an input parameter in the webblock named: InputIdToStoreCheckBoxes

2. Delete the web block javascript

3. Drag an expression to the screen:
Name:
Example: javascript related to checkboxes
Escape Content: No
Value:

"<script type=""text/javascript"">
//<![CDATA[

function SetResetCheckBox(checkbox){
 var elem = document.getElementById(""" + InputIdToStoreCheckBoxes + """);  
 if(checkbox.value=='on'){  
   //...
   elem.value = elem.value + ',' + checkbox.id;
   //..
 } else {
   //...
 }
}

//]]>
</script>
"

-- In the page:
Pass this argument to the webblock input param: InputConcatenatedCheckboxes.Id
avieira wrote:
3. Drag an expression to the screen:
 
:(
You were doing so well with the webblock javascript, and had to ruin it with an unescaped expression.

What about passing the InputIdToStoreCheckBoxes as parameter to the method?

Regards,
João Rosado
Thanks a lot. Actually, I solved it by adding an extra parameter to the JS function, then in the oncheck property, instead of simply having the same standard call to the function each time, I created a string which included the ID that had been passed in to the webblock as a parameter. That way, I was also add other items into the JS function that were also necessary (record IDs) for the functionality to work, like this:

"SetResetCheckBox(this, 
'" + ChangesTextBoxName + "', " 
+ GetPeople.List.Current.Person.Id + ", " 
+ EventId + ")"
That way, I can pass anything into the function that I need, and the output all goes to the field indicated by the 'ChangesTextBoxName' parameter.

Thanks for all your help, I've now got a really fast app compared to yesterday!
Spoke too soon...

What I've just found is it all works fine with the text box on the main page set to be visible, but when I set the tex box that holds the info in to be not displayed, it is then not included in the HTML, so a javascript error is thrown when it tried to access it.

Any ideas?
That behavior is probably for security reasons.

Just create a css class with "display: none":

.Invisible {
    display: none;
}

and use this style in the input:

Style: Invisible



@avieira amazing, thanks so much - we're all working now!