# How to get dynamic results of the values in three InputFields

I have three InputField-s which have no initial value. I would like all InputFields to have a value in descending order and for each InputField, a "right" and "wrong" symbol should be displayed as soon as some value is entered in any of these InputFields.

The user can enter his first value, say 89 in any of the InputField between 100 and 0. It will always show "right" symbol as all other InputField-s are empty. If he choose the next InputField to be filled in the right hand side of the previous InputField, then that value should be between 89 and 0 else it should show wrong dynamically. And If he chooses some other InputField to be filled in the left hand side of the first InputField, then that value should be between 100 and 89 else it is wrong.

I faced the problem when I skipped the first InputField and entered 76 in the second InputField. It looked alright but as soon as I entered 89 in the third InputField, both were shown as wrong.

logicalInputField[i_, numberOfFields_, tx_, symbol_, upperLimit_,
lowerLimit_, noValue_, right_, wrong_] :=
(txtx = tx; sysy = symbol; upup = upperLimit;lolo = lowerLimit; nono = noValue; riri    = right; wrwr = wrong;
Column[{InputField[Dynamic[txtx[[i]]], Number, FieldSize -> 3,
Alignment -> {Center, Center}, ContinuousAction -> True],
( Dynamic[(  If[txtx[[i]] == Null,    (txtx[[i]] = ""; sysy[[i]] = noValue), (sysy[[i]] = right)    ];
For[j = i - 1, j >= 1, j--, If[txtx[[j]] != "", (upup[[i]] = txtx[[j]]; Break[];),
""]];
For[k = i + 1, k <= numberOfFields, k++,
If[txtx[[k]] != "", (lolo[[i]] = txtx[[k]]; Break[];),
""]];
If[txtx[[i]] >= lolo[[i]],
(sysy[[i]] =
right;), (sysy[[i]] = wrong;)   ];
If[lolo < txtx[[i]] <= upup[[i]],
(sysy[[i]] =
right;), (sysy[[i]] = wrong;) ];

sysy[[i]] )    ])   }]) ;

DynamicModule[{s = {}, enterValue = "ENTER", correct = "RIGHT", incorrect = "WRONG"}, For[i = 1, i <= 3, i++,  DynamicModule[{i = i},
AppendTo[s, logicalInputField[i, 3, {"", "", ""}, {enterValue, enterValue, enterValue}, {100, 100,
100}, {0, 0, 0}, enterValue, correct, incorrect]]] ];
Panel[ Row[s, Spacer[0]]]]

-
Consider proving an example of the problem you are facing. Without the code that's causing the problem, it's very difficult to figure out what could be causing it. –  jVincent Sep 25 '12 at 13:46
@jVincent: I have added the code. –  Jennifer Sep 25 '12 at 17:04

My guess is it's due to the "direction" you're comparing the numbers in, though honestly I'm having trouble reading your code. Here's the general approach I would use for doing something like this:

descending[numberOfFields_] := DynamicModule[{
numbers = {Infinity} ~Join~ ConstantArray[100, numberOfFields]},

Grid[Table[
{DynamicModule[{is = i}, Checkbox[Dynamic[numbers[[is]] < numbers[[is - 1]]], Enabled -> False]],
DynamicModule[{is = i}, InputField[Dynamic[numbers[[is]]]]]},
{i, 2, numberOfFields + 1, 1}]]
];

descending[3]


General note: You can use Tab to cycle through inputs and update Dynamic elements.

-

I took a different approach, using the second argument of Dynamic, and generalized it to any number of InputFields. The list of input values is stored in list, their evaluations (eval) to "Right", "Wrong" or "Enter" (indeterminate) is calculated on the fly by comparing from right to left. This means that entering a nonnumerical value in the 2nd position makes the test to fall back to "Enter" for the next entries to the right, as they cannot be compared to the entry at position 2. This also causes that any entry after a "Wrong" entry will be evaluated to "Wrong".

n = 5;(*number of InputFields*)
list = Array["" &, {n}];(*user input values*)
eval = Array["Enter" &, {n}];(*"Enter","Right" or "Wrong"*)

Panel@Dynamic[Grid@{
InputField[Dynamic[list[[#]], Function[{$x}, list[[#]] =$x;
eval =
If[NumberQ@list[[#]],
If[Greater @@ Take[list, #], "Rigth", "Wrong", "Enter"],
"Enter"] & /@ Range@n]], Number, FieldSize -> 3,
ContinuousAction -> True] & /@ Range@n,
eval
}, TrackedSymbols :> {eval}]


Updated

As OP has further specified the problem, here is an evolved version, that always accepts the first input (if it is a number) regardless of position, and checks successive inputs against their neighbours and also rechecks the full eval list, so that later corrections at e.g. the left side could render previously wrong results good:

Also, comparison always starts from left, so the following can be expected:

Since ContinuousAction won't work seamlessly (InputFields keeps loosing focus during typing) if the whole Grid is wrapped in Dynamic[..., TrackedSymbols :> {eval}], I split the Grid to two, and resized them with ItemSize.

n = 5; (* number of InputFields *)
neighbours = {};
list = Array["" &, {n}];(* user input values *)

{right, wrong, enter} = {Checkbox@True, Checkbox[Null, {True, False}], Checkbox@False};
eval = Array[enter &, {n}];(* list to store enter/right/wrong data *)

Panel@Column@{
Grid[{
InputField[Dynamic[list[[#]], Function[{$x}, list[[#]] =$x;
neighbours =
DeleteCases[Take[list, {Max[1, # - 1], Min[n, # + 1]}], ""];

(* check whether the actual field in focus has correct value or not *)
eval[[#]] = If[And @@ (NumberQ /@ neighbours),
If[Greater @@ neighbours, right, wrong], right, enter];

(* update all other eval fields according to the new value of the focus field *)
eval = If[NumberQ@list[[#]],
If[Greater @@ DeleteCases[Take[list, #], ""], right, wrong], enter] & /@ Range@n;
]], Number, FieldSize -> 3, ContinuousAction -> True] & /@ Range@n
}, ItemSize -> 4],
Dynamic@Grid[{eval}, ItemSize -> 4]
}

-
This is something different from what I am looking. I have edited my question for better understanding. –  Jennifer Sep 26 '12 at 9:13
@Jennifer Please check edit. –  István Zachar Sep 26 '12 at 12:24