Defining Variables for Instance of Grid Application (Menutab Selection)

I have a project that uses a menu application as a front end to about 40 reports. Each report uses the same grid application(mygrid), with a different WHERE clause in the SQL to select the appropriate data. In the menu application, I set the value of two global variables, [title] and [dataselection]. [title] is used in the Grid Title and [dataselection] in the grid SQL - SELECT col1,col2,…
WHERE area IN ([dataselection]).

This works without issue as long as I am viewing the most recent report that was opened. If I open the report for area1, then open the report for area2 and then return to area1, if I perform any action that regenerates the grid, the WHERE clause picks up the last value of [dataselection] and [title], which in my example are actually the values for area2.

I can duplicate the grid application 40 times, and alter the SQL and grid title, but that creates a maintenance headache should the report need to change.

What I need is a way to define variables that are not local ($myvar) which are limited in scope to a Scriptcase event inside an application (mygrid), not global ([myvar]), which are accessible to all applications in the project, not application-specific (attributes?), since mygrid is reused 40 times, but rather menu tab (iframe) specific, so that when a report is invoked from the menu application, variables are saved and accessible only to that instance of the application (menu tab/iframe). The variables need to persist so that the grid pulls the correct data when refreshed.

Any ideas?

If your reports are generated by the menu I would suggest to set the globals in the menu event, not in the underlying grids. in fact, I think that you could do with only one grid, where you set the parameters in the menu.

I am setting the globals in the On Execute event of the menu. For example, $area = {sc_menu_item}; Then I use a switch statement on $area. In each case block, I set [dataselection] and [title] to the correct values.

something is wrong with the forum application…

To create an app “local” variable, I’ve seen a post by Giu that suggested to get the passed IN variable and assigning its value to an OUT variable with all Scopes disabled.

If I understood Giu’s post correctly, it should be something like this:


OnScriptInit
[dataselection] = [dataselection_IN];

[dataselection_IN] is set as type IN and scope set to GET\POST. This is the variable passed by the menu app.
[dataselection] is set as type OUT and all scopes GET\POST\SESSION are unchecked. This is the variable used by the grid SQL statement.

I have no idea if it will work in your case :slight_smile:
If not, I’m not sure it will make any difference, but I’d also try to add a sc_reset_global().


OnScriptInit
[dataselection] = [dataselection_IN];
sc_reset_global([dataselection_IN]);

Roby-

Your clarification helped me understand Giu’s concept. Thank you.

That said, I am not having much success with this.

When the input global variable is reset, an error message is triggered about a missing global variable. If I set the input global variable to optional, no error message is displayed, but it still seems to pick up the last global input value from the other window (very odd). I believe that the concept that Giu and you proposed should work. I do not know if there is a bug in Scriptcase.

When I analyzed changes to the $GLOBALS array, $_GET was blank and $_POST had limited parameters. It seems that Scriptcase may be passing parameters through $_SESSION - and managing rules of GET/POST/SESSION internally.

Perhaps I am a little bit closer to my goal. I can now determine in OnScriptInit whether the event was triggered by the menu or by a grid refresh. I can also determine which menu item was selected by parsing $_SERVER[‘HTTP_REFERER’] and looking for parameter ‘sc_item_menu’. Here is the OnScriptInit code to do that:

parse_str(parse_url($_SERVER[‘HTTP_REFERER’], PHP_URL_QUERY), $qstring);
if (isset($qstring[‘sc_item_menu’])) {
// triggered by menu
}
else {
// triggered by something else
}

At this point I could move the switch statement from the menu and into the grid, which would set the proper values for the SQL WHERE.

But I need to persist a variable somewhere that is unique to the application instance and then retrieve that value when the grid is refreshed.

I was thinking of perhaps storing the value in a form with a hidden input field, but if I am not seeing $_GET/$_POST variables in the $GLOBALS array, I’m not sure it this approach has merit.

Maybe you should move the variable setting code to onApplicationInit.

That event shouldn’t be retriggered by a grid refresh I think.

One more try could be to protect the setting of the variable if already set:

If (empty([dataselection]))
{
[dataselection] = [dataselection_IN];
}

Moving the variable setting code to onApplicationInit prevented it from being triggered by a grid refresh.

Unfortunately, the grid pulls the last value of the variable despite our efforts to prevent that from happening.

Protecting the setting of the variable as you suggested did not have the desired effect.

Sorry but I give up.

I guess this is a lost battle; you’re setting the same [dataselection] variable from the same application, so I have no idea how to make it work.
Maybe some of the more experienced SC gurus could help you.

" If I open the report for area1, then open the report for area2 and then return to area1, if I perform any action that regenerates the grid, the WHERE clause picks up the last value of [dataselection] and [title]"

Can you clarify what do you mean by “then return to area 1”? How? I guess not via the menu app as that would set the variable to the proper value.
I think you’re having this issue because you can have multiple reports open at the same time, right? (maybe as tabs?)
If there’s no other way, maybe you could “redesign” your app to make it have only one instance of the reports open at one time.

1 Like

I think he probably is using tabs.
If you have a paid support, I know people could easily help you out here.

Roby- First, thank you for all your help in trying to solve this. Sorry for confusing you. I am using tabs and with multiple menu selections, that is how more than one instance of the application can set and access the same global variable. I have been experimenting with code to close all other tabs (except for the current one) and that may be the best option.

Cavadinha- I do have paid support and I have followed your suggestion by opening up a ticket. Thank you as well.

I will continue to post information as it becomes available…

Problem could be menus don’t likes to much globals. Use $_SESSION[“yourglobal”] superglobal.

Otherwise, without seeing the code is difficult to say. Can you share the code calling a menu item, and the the code to assign the where filter?

Giu the issue is that even with variables scope restricted to an app, with multiple instances of the same app running, the app can break.

Maybe bradk cans solve this particular issue, but so far I’m not using tabs because I’ve found scenarios where conflicting variables assignment did happen.

Some of these issues seem solvable when the value can be read via ajax/js from the rendered web page (that is per instance by definition).
But in some cases I was not able to solve them, especially in grids apps.

If NetMake could provide a way to define variables per app instance, it would make life much easier.

I am able to parse the iframe to determine which menu item was selected and store in in a JS variabale. The problem is how to take that JS variable from the browser and send it back to PHP in OnScriptInit. I’m not sure I can use jQuery $.ajax to do this. For example, I can create superglobals $_SESSION[“menu1”], $_SESSION[“menu2l”] in the menu application. When the menu selection loads for the first time, I can determine which menu item was chosen and store it in a JS variable, e.g. jmenu1. But how to connect the JS variable and PHP in a grid when SC ajax macros are not available to me is a challenge. Inpsecting changes to $GLOBALS before and after a grid refresh suggests an ajax process within SC, not a GET/POST where I could create a form containing the JS variable as a hidden field and then grab in inside OnScriptInt with $_GET[var]/$_POST[var]. Brilliant ideas are always welcome:)

bradk,

I tried this logic

STORING A VAR NAMED [SC_variable] PER INSTANCE

$var_value = [SC_variable];
$var_name = “SC_variable”;
echo “<script>js_session_var_write(’$var_name’, ‘$var_value’);</script>”;

function js_session_var_write(var_name, var_value)
{
//
// goal: 1) store var_name name and a unique instance ID on the client
.for any var_name, accessing the var_instance_id on the client and query the server for the var_value.
//

// get a unique id per isntance
var_instance_id = guid(); // guid is a js function to generate a unique ID

// save var_name = var_instance_id on the client via jquery
$.data( document.body, var_name , var_instance_id );

// save var_instance_id = var_value on the server via ajax.
$.post(’…/blank_session_var_repo/index.php’,{name: var_instance_id , value: var_value});

}

READING THE VAR INSTANCE

$var_value = php_session_var_reader($var_name);
function php_session_var_reader(var_name)
{
$read_token = uniqid();
echo "
<script>
var_instance_id = $.data( document.body, ‘$var_name’); // get the var_instance_id from the document
$.post(’…/blank_control_app_var_instance_test/index.php’,{name: ‘$read_token’, value: instance_id}); //associate a unique read token to the var_instance_id so that later we can retirve it from the server
</script>
";

}

Hello bradk.
Were you finally ableto solve your issue ?
I’m having the exact same issue described here : Insert detail with master id - mix of master id when using global variable
And so far I haven’t been able to solve it. Because of this I’m exploring other system than Scriptcase because working with several “clients” (grid or form) at the same time is a requirement.
Let me know. Thanks.

I am interested too.
Basically the question is:
Is it possibile to have several instances of the same app running in the same browser at the same time on different data ?

Full disclosure, it has been many years since I last used Scriptcase. I’m sure the product has advanced quite a bit from where I left off. That said, I may have an idea on how to achieve this (based on my experience in native PHP, HTML/CSS/JS), but it may or may not apply to Scriptcase.

When a user clicks on the master table to select a record to edit, I would set a global (PHP session) variable and also a JS variable (I will explain why and how to do this later). This variable would be used to identify the record id that is currently selected for editing. When the user clicks on a field, I would also set a global variable and JS variable. This additional pointer would identify the detail table that the user wants to edit. (Note: You will likely need to add some extra classes or data attributes to the HTML to uniquely identify rows.) The reason you need to set both global (PHP) and JS variables is to make them accessible to client (JS) and server (PHP) code. When a user changes the value via a form, the CANCEL and SAVE buttons need to take the proper action, but also need to clear both the global and JS variables that tell the application which master/detail combination is currently being edited. When a client action requires the application to reset a pointer variable, use an AJAX call to reset the global variable (I recall Scriptcase has that as a native function). When a server action resets a pointer variable, use PHP code like this: echo '<script>var thisvar="' . $phpvar . '";</script>'; to trigger the same change in the client.

This approach assumes only one detail table will be edited at a time to prevent application confusion. I would consider blocking other screens with a semi-transparent layer that prevents the user from clicking on buttons underneath the top layer.

It might be possible to expand on this idea, eliminating the one detail form at a time limit, and allow multiple forms to be open at the same time by setting a pointer array variable instead of pointer variables. When a form is saved or cancelled, you would need to use the form name, id or hidden field to identify not only which value(s) to save, but also which pointer element to remove from the array. Your code should loop through the array of “open detail forms” until a match is found.

While I believe that this could be accomplished using native PHP/HTML/CSS/JS, I am not sure that all of these concepts will be possible by using the built-in features of Scriptcase. Those features save a lot of time, but can also make some native coding a bit more challenging.

I hope this helps. But if it is totally in the wrong direction because of the Scriptcase environment or your specific application requirements, just ignore this post:)

Yes bradk. This is the way.
See my post here Using same app in two browser tabs. Safe?
Hope it helps you guys. It worked for me.