Dialogs and Dynamic

Initialize global list of {string, number} pairs

main = {{"apple", 1}, {"banana", 2}, {"carrot", 3},{"donut", 4}

Function to edit item number j from the list

EditItem[j_] := Module[{tx, nm},
  tx = main[[j]][[1]];
  nm = main[[j]][[2]];
  CreateDialog[{
    Panel[
     Column[{
       InputField[Dynamic[tx], String],
       InputField[Dynamic[nm], Number],
       Row[{
         CancelButton[],
         DefaultButton[
          "Save",
          main[[j]][[1]] = tx;
          main[[j]][[2]] = nm;
          DialogReturn[]
          ]
         }]
       }]
     ]
    }, Modal -> True]
  ]

If I call the edit function directly, it works fine.

EditItem[4]
NotebookObject[FrontEndObject[LinkObject["tp8_shm", 3, 1]], 110]
main
{{"apple", 1}, {"banana", 2}, {"carrot", 3}, {"dingbat", 5}}

If I call the edit function from the buttons in this dynamic table, it doesn’t work. The fields are not pre-populated and the assignments fail.

In[11]:= Dynamic[
 Panel[
  Grid[
   Table[{Button[main[[j]][[1]], EditItem[j]], main[[j]][[2]]}, {j, 1, Length[main]}]
   ]
  ]
 ]

Why doesn’t the function call work from inside the buttons?

I’ve been using Mathematica for 20+ years, but only recently tried to understand Dynamic and UI features.

Dynamics can be very tricky. I think that the following changes make your function work the way you want.
Main changes to note:

  • Use of DynamicModule instead of Module
  • Use With inside Table

main = {{“apple”, 1}, {“banana”, 2}, {“carrot”, 3}, {“donut”, 4}};
EditItem := DynamicModule[{tx, nm},
tx = main[][[1]];
nm = main[][[2]];
CreateDialog[{Panel[
      Column[{InputField[Dynamic, String],
        InputField[Dynamic, Number],
        Row[{CancelButton[], DefaultButton[“Save”, main[][[1]] = tx;
           main[][[2]] = nm;
           DialogReturn[]]}]}]]}, Modal → True]
];

Panel[Grid[Table[
With[{j = j},
    {Button[main[][[1]], EditItem],
     Dynamic[main[][[2]]]}], {j, 1, Length}]]]

Perfect! Thank you. I’ve run into the need for With before but I still have no instinct for why it’s necessary sometimes.

The With basically converts the i index into a number instead of a variable. That way your app is making reference to i as a number instead of a local variable which would be unrecognizable after you use it the first time. This happens because indexes in Table are indeed local variables to the Table. These local variables disapear after the Table is used, thus, without the With your Dynamic app would be making reference to an unexisting variable.

After your comment I went back and re-read the “A Good Trick to Know” bit in the Intro to Dynamic help for the 100th time, but this time it made sense. Thanks!