CALL METHOD and -> behave differently for ALV events. Why? - events

I hope that i got the title right because i seriously can't think of a short description for this scenario. I'll try to make it brief:
I have an editable ALV which displays some data and whenever the User inputs data and changes the active cell (e.g. clicks on another cell, presses an arrow key,etc.) the event "data_changed" of the ALV grid should be triggered.
Now to my question:
When I use the following code
* ENTER key is pressed
CALL METHOD go_grid->register_edit_event
EXPORTING
i_event_id = cl_gui_alv_grid=>mc_evt_enter.
* data is changed and cursor is moved from the cell
CALL METHOD go_grid->register_edit_event
EXPORTING
i_event_id = cl_gui_alv_grid=>mc_evt_modified.
The event is triggered as it should be. However when I use:
go_grid->register_edit_event( i_event_id = cl_gui_alv_grid=>mc_evt_enter ).
go_grid->register_edit_event( i_event_id = cl_gui_alv_grid=>mc_evt_enter ).
No event is triggered when i do the same actions.
But aren't these 2 ways basically the same or are they functioning differently from each other? Documentation also states that CALL METHOD is obsolete and shouldn't be used anymore.

You read correctly: CALL METHOD foo->bar EXPORTING x = y. and foo->bar( x = y ). do the exact same thing. They are alternative syntax for the same functionality.
The difference in behavior you encounter might be because you are not actually doing the same thing in both code snippets.
In the first snippet, you pass mc_evt_enter to the first method call and mc_evt_modified to the second method call. But in the second code snippet, you pass mc_evt_enter to both method calls.
Try this:
go_grid->register_edit_event( i_event_id = cl_gui_alv_grid=>mc_evt_enter ).
go_grid->register_edit_event( i_event_id = cl_gui_alv_grid=>mc_evt_modified ).

Related

Writing value of FormGroup FormControls in Angular

I have an array of FormControls in an inventory application in which I am trying to update a single item in the form based on a change - by another user on another device - in the value in the back end. (Firebase in my case.)
I have access to the FormControl and I am able to make that change... except not. Here's the situation:
You'll not from the console output, that when I expand the FormGroup and look at the value I see 3. This is the correct value from the back end. But the FormGroup.controls.current.value is still 4... the old value in the form.
I've been trying to play with different methods of accessing this control to get it to update properly.
Here's the code:
this.items.controls.forEach((item, index) => {
if (item.value.current != this.inventoryElements[index].current) {
//First attempt to change the value of the formControl
this.items.value[index].current =
this.inventoryElements[index].current;
//Second attempt
this.items.controls[index].value.current =
this.inventoryElements[index].current;
//Third attempt
item.value.current = this.inventoryElements[index].current;
console.log(this.items.controls[index]);
console.log(this.items.controls[index].value.current);
console.log(this.items.value[index].current);
}
});
this.inventoryElements[index].current holds the value I want to put into the form control.
this.items is the array of Form Controls.
You can see that I made three attempts to get the value there without luck -
The first console.log results in 4.
The second console.log results in 4.
The third console.log results in the output pasted at the top of this question.
One more piece of background. The FormArray is this {current: string, notes: string} and my attempt was to modify the current value.
By the way, the reason I'm going through all of this mess is that I was unhappy that an update of a single value in the back end would cause the entire page to reload. So this was an attempt to see whether I could update a single value and avoid the whole page reload.
Thanks the the help.
Paul
The third attempt was close. Instead of assigning the value with an equals sign:
item.value.current = this.inventoryElements[index].current;
Use patchValue
item.patchValue({
current: this.inventoryElements[index].current});

iup.GetParam in LUA: data validation in the callback function

LUA novice, experimenting with GUI using iup.GetParam using LUA 5.1.
I have a simple use of iup.GetParam (which works fine with a simple callback function testing for OK & Cancel) and am trying to add some simple data validation for the parameters (e.g. testing a parameter for being alphanumeric), but am unsure of the correct approach.
I've searched the reference manual (and for code examples), but drawn a blank so far.
Using the string validation example, if I want to reject the
character entered by the user and display the old value of the
parameter, do I simply return 0 from the callback function, or, do
I also have to reset the value of the parameter to its previous
value before the return? Or is the right approach something
completely different?
In either case, do I have to refresh / update the GUI display with a
separate iup call, or does GetParam handle that for me?
Whatever combination I try, it doesn't appear to work (the parameter happily displays the non-alphanumerics). Debugging shows the validation test and return working as coded, so the advice I'm seeking is to get confirmation of the right approach. Sharing a simple working example would be great.
simply return 0
No, IUP will do everything for you, in this case
Download the "getparam.wlua" from the examples folder, then add to its callback this:
elseif (param_index == 1) then
return 0
You will notice that the integer value is now read-only.

How to get content between HTML tags that have been loaded by jQuery?

I'm loading data using jQuery (AJAX), which is then being loaded into a table (so this takes place after page load).
In each table row there is a 'select' link allowing users to select a row from the table. I then need to grab the information in this row and put it into a form further down the page.
$('#selection_table').on('click', '.select_link', function() {
$('#booking_address').text = $(this).closest('.address').text();
$('#booking_rate').text = $(this).closest('.rate').val();
});
As I understand it, the 'closest' function traverses up the DOM tree so since my link is in the last cell of each row, it should get the elements 'address' and 'rate from the previous row (the classes are assigned to the correct cells).
I've tried debugging myself using quick and dirty 'alert($(this).closest(etc...' in many variations, but nothing seems to work.
Do I need to do something differently to target data that was loaded after the original page load? where am I going wrong?
You are making wrong assumptions about .closest() and how .text() works. Please make a habit of studying the documentation when in doubt, it gives clear descriptions and examples on how to use jQuery's features.
.closest() will traverse the parents of the given element, trying to match the selector you have provided it. If your .select_link is not "inside" .address, your code will not work.
Also, .text() is a method, not a property (in the semantical way, because methods are in fact properties in Javascript). x.text = 1; simply overrides the method on this element, which is not a good idea, you want to invoke the method: x.text(1);.
Something along these lines might work:
var t = $(this).closest('tr').find('.address').text();
$('#booking_address').text(t);
If #booking_address is a form element, use .val() on it instead.
If it does not work, please provide the HTML structure you are using (edit your question, use jsFiddle or a similar service) and I will help you. When asking questions like this, it is a good habit anyways to provide the relevant HTML structure.
You can try using parent() and find() functions and locate the data directly, the amount of parent() and find() methods depends on your HTML.
Ex. to get previous row data that would be
$('#selection_table').on('click', '.select_link', function(){
$('#booking_address').text = $(this).parent().parent().prev().find('.address').text();
});
Where parent stands for parent element (tr), then prev() as previous row and find finds the element.
Is there a demo of the code somewhere? Check when are you calling the code. It should be after the 'success' of AJAX call.

How to create dynamic Callbacks in MATLAB?

I have this line of code:
delete_btn = uicontrol(rr_ops, 'Style', 'pushbutton', 'String', 'Delete Graphic', 'Position', [13 135 98 20], ...
'Callback', 'delete_graphic');
and a little bit upper this function:
function delete_graphic
global rr_list
selected = get(rr_list, 'Value');
selected
return;
why this code is not working? I really dont understand...
What do I need? I create one button and a listbox, clicking on button - deleting selected element from a listbox.
Thx for help.
PS
Always getting this error:
??? Undefined function or variable 'delete_graphic'.
??? Error while evaluating uicontrol Callback
here is all my code: http://paste.ubuntu.com/540094/ (line 185)
The generally-preferred way to define a callback function is to use a function handle instead of a string. When you use a string, the code in the string is evaluated in the base workspace. This means that all the variables and functions used in the string have to exist in the base workspace when the callback is evaluated. This makes for a poor GUI design, since you don't really want the operation of your GUI dependent on the base workspace (which the user can modify easily, thus potentially breaking your GUI).
This also explains the error you are getting. The function delete_graphic is defined as a subfunction in your file rr_intervals.m. Subfunctions can only be called by other functions defined in the same m-file, so delete_graphic is not visible in the base workspace (where your string callback is evaluated). Using a function handle callback is a better alternative. Here's how you would do it:
Change the callback of your button (line 216) from 'delete_graphic' to #delete_graphic.
Change the function definition of delete_graphic (line 185) to:
function delete_graphic(hObject,eventdata)
where hObject is the handle of the object issuing the callback and eventdata is optional data provided when the callback is issued.
EDIT:
If you want to pass other arguments to delete_graphic, you can perform the following steps:
Add the additional input arguments to the end of the function definition. For example:
function delete_graphic(hObject,eventdata,argA,argB)
Use a cell array when you set the callback for your button, where the first cell contains the function handle and the subsequent cells each contain an input argument. For example:
set(delete_btn,'Callback',{#delete_graphic,A,B});
There is one caveat to this, which is that the values A and B stored in the cell array are fixed at what they are when you set the callback. If you change A or B in your code it will not change the values stored in the cell-array callback.
If you aren't able to use the above solution (i.e. if A and B need to change value), there are a few other options for how you can share data among a GUI's callbacks:
You can rework the organization of your code to make use of nested functions. This makes it very easy to share data between callbacks. Some nice examples of using nested functions to create GUIs can be found in the MathWorks File Exchange submission GUI Examples using Nested Functions by Steven Lord.
You can store data in the UserData property of a uicontrol object. To access or update it, you just need the object handle.
You can use the functions SETAPPDATA/GETAPPDATA to attach data to a handle graphics object (i.e. uicontrol).
Since it appears your code was created using GUIDE, you can make use of the handles structure GUIDE creates to store data using the GUIDATA function.

Column Tree Model doesn't expand node after EXPAND_NO_CHILDREN event

I am displaying a list of items using a SAP ABAP column tree model, basically a tree of folder and files, with columns.
I want to load the sub-nodes of folders dynamically, so I'm using the EXPAND_NO_CHILDREN event which is firing correctly.
Unfortunately, after I add the new nodes and items to the tree, the folder is automatically collapsing again, requiring a second click to view the sub-nodes.
Do I need to call a method when handling the event so that the folder stays open, or am I doing something else wrong?
* Set up event handling.
LS_EVENT-EVENTID = CL_ITEM_TREE_CONTROL=>EVENTID_EXPAND_NO_CHILDREN.
LS_EVENT-APPL_EVENT = GC_X.
APPEND LS_EVENT TO LT_EVENTS.
CALL METHOD GO_MODEL->SET_REGISTERED_EVENTS
EXPORTING
EVENTS = LT_EVENTS
EXCEPTIONS
ILLEGAL_EVENT_COMBINATION = 1
UNKNOWN_EVENT = 2.
SET HANDLER GO_APPLICATION->HANDLE_EXPAND_NO_CHILDREN
FOR GO_MODEL.
...
* Add new data to tree.
CALL METHOD GO_MODEL->ADD_NODES
EXPORTING
NODE_TABLE = PTI_NODES[]
EXCEPTIONS
ERROR_IN_NODE_TABLE = 1.
CALL METHOD GO_MODEL->ADD_ITEMS
EXPORTING
ITEM_TABLE = PTI_ITEMS[]
EXCEPTIONS
NODE_NOT_FOUND = 1
ERROR_IN_ITEM_TABLE = 2.
It's been a while since I've played with SAP, but I always found the SAP Library to be particularly helpful when I got stuck...
I managed to come up with this one for you:
http://help.sap.com/saphelp_nw04/helpdata/en/47/aa7a18c80a11d3a6f90000e83dd863/frameset.htm, specifically:
When you add new nodes to the tree model, set the flag ITEMSINCOM to 'X'.
This informs the tree model that you want to load the items for that node on demand.
Hope it helps?
Your code looks fine,
I would use the method ADD_NODES_AND_ITEMS myself if I were to add nodes and items ;)
Beyond that, try to call EXPAND_NODE after you added the items/nodes and see if that helps.

Resources