Subscribe for automatic updates: RSS icon RSS

Login icon Sign in for full access | Help icon Help
Advanced search

Pages: [1]
  Reply  |  Print  
Author Topic: Function to detect if user changed anything?  (Read 9142 times)
Bryce S.
Posts: 52


« on: May 20, 2010, 05:41:10 am »

Hi,

I wrote a wee function (see below) to try to detect if a user has changed anything in a form by searching through the dom tree and testing fields with dialog.getFieldTouched().

However, I've been burned before by doing things with the dom tree and then it changes between versions.

Is there any chance of fourjs supplying a function to detect if the user has changed any values in a form? (hint. feature request). I use this primarily with 'on action cancel' or 'on action accept' to decide whether to warn user about losing changes or to go and save the changes.

Also, if anyone has a better way of testing for any changes easily please post your suggestions, or improvements on function below. Thanks.


function AnyFieldTouched( the_dialog )
define
     the_dialog        ui.Dialog,
     window_ui        ui.Window,
     window_node   om.DomNode,
     node_list          om.NodeList,
     node_item        om.DomNode,
      i                     smallint,
      field_name      string,
      field_id            string,
      change_made  boolean

let change_made = FALSE

let window_ui = ui.Window.getCurrent()
let Window_Node = window_ui.getNode()
let node_list = Window_Node.SelectByPath("//FormField")
for i = 1 to node_list.getLength()
   let node_item = node_list.item(i)
   let field_id = node_item.getAttribute("fieldId") clipped
   if length(field_id) then
       if node_item.getAttribute("active") = 1 then
           let field_name = node_item.getAttribute("name") clipped
           if the_dialog.getFieldTouched(field_name clipped) then
               let change_made = TRUE
               exit for
           end if
      end if
  end if
end for

# above block repeated searching for 'TableColumn' instead of 'FormField' to handle arrays -
# but results not as accurate as doesn't detect deleted row, nor values changed and then changed back as being 'no change'.

return change_made
end function


Regards,
  Bryce Stenberg
Sebastien F.
Four Js
Posts: 509


« Reply #1 on: May 20, 2010, 10:16:46 am »

Bryce,

For such need you should not have to write complex code digging in the AUI tree!

There are different techniques...

If you want to check if one of the fields was modified (i.e. touched), you can use FIELD_TOUCHED() or DIALOG.getFieldTouched().
You can pass screen_record_name.* to these functions in order to check all fields, and/or pass a list of fields.

https://4js.com/techdocs/genero/fgl/devel/DocRoot/User/MultipleDialogs.html#touched-flag

Note that especially for multiple dialogs, I would prefer to detect that the user has started to modify a field with the new dialogtouched action, in order to enable the possible actions and disable the others. This way, you don't even let the user validate the dialog (save/ok) until it has started to modify fields.

See demos in FGLDIR/demo/MultipleDialogs

and:

https://4js.com/techdocs/genero/fgl/devel/DocRoot/User/MultipleDialogs.html#detecting-changes

Seb
Bryce S.
Posts: 52


« Reply #2 on: May 21, 2010, 07:11:18 am »

Note that especially for multiple dialogs, I would prefer to detect that the user has started to modify a field with the new dialogtouched action, in order to enable the possible actions and disable the others. This way, you don't even let the user validate the dialog (save/ok) until it has started to modify fields.

Thanks Seb,

I like the examle code here (
https://4js.com/techdocs/genero/fgl/devel/DocRoot/User/MultipleDialogs.html#detecting-changes ), especially turning off the dialogtouched action once you detect changes start to be made.  But it can't help me where user changes a value then changes it back again (they have been known to do that) - getDialogTouched would see that as no change - dialogtouched 'detecting-changes' example would say it is changed.

You can pass screen_record_name.* to these functions in order to check all fields, and/or pass a list of fields.

That's good to know - I didn't realize I could pass records to the getFieldTouched function. In my current program there are potentially 7 folder tabs with 7 associated display arrays - but not all may be in use and displayed. Instead of having to write code to decide if I need to check a particular array and call getFieldTouched up to seven times it would be nice to just pass the 'dialog' and be returned a true/false value for anything changed or not.

In some programs there can be 20 odd seperate fields to check - I'm never keen on writing that much repetitive code to see if anything changed. So any chance of a single function call that can check the current dialog to see if any actual changes occurred? In the meantime I may continue to use my function, even though it doesn't work 100% for arrays. If I can cobble that piece of code together in half an hour to try to work out any changes in a dialog, I thought you guys could do a much better job of it that may be supported?

Maybe I'm just lazy - I prefer to write one line of code per dialog instead twenty or so to accomplish the same thing...
It could be the way I write code is the problem however - does anyone else think it would be a good thing to have a function that tells you if any changes occured in the current dialog?

Regards, Bryce Stenberg.
Sebastien F.
Four Js
Posts: 509


« Reply #3 on: May 21, 2010, 09:56:00 am »

Hello Bryce,

In the case of changing back a value, I believe that you could use dialogtouched in conjunction with the "before-modification-record" technique to check that there has been a real change. Anyway this is my recommendation for concurrency handling (i.e. Optimistic Locking).
See this for details:
https://4js.com/techdocs/genero/fgl/devel/DocRoot/User/SqlProgramming.html#PORT_OPTLOCK

Keep also in mind that DISPLAY TO / BY NAME will set the touched flag, but you do not have to use these with UNBUFFERED dialog attribute.

Regarding the global dialog function to detect changes, I will talk with others here about the request.
Maybe we could use a simple star to indicate "all fields used by the current dialog":
  IF FIELD_TOUCHED(*) THEN
and
  IF DIALOG.getFieldTouched("*") THEN
...
Request filed as: #17112

You wrote that you have 7 folder tabs with 7 display arrays, not all used at the same time (i.e. not running concurrently in a DIALOG block)... I would STRONGLY suggest to split your window into several sub-windows. Does it harm to get another window pop-up when accessing one of the lists? Are you using GDC or GWC? This certainly matters in the form design...

Don't miss-use the folder-tabs by writing HUGE forms: Next complain will be that programs take time to start... ;-)

Seb
Bryce S.
Posts: 52


« Reply #4 on: May 24, 2010, 12:12:15 am »

Hi Seb,

Using the * in getFieldTouched and field_touched sounds great - thanks for filing the request.

And my example with 7 tabs and arrays - they are all in the one dialog statement so is ok - some are just not populated or displayed depending on values found in the database.

Thanks for listening.
Regards,
  Bryce Stenberg.
Pages: [1]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines