1
$\begingroup$

I'm creating a user interface for data entry. It makes sense for the content of certain menu items to depend on the information that has been entered earlier on the form.

In a trivial example, imagine a DialogWindow where selecting menu item "Bill" results in a PopupMenu with the choices "Running" or "Reading", while selecting the item "Susan" results in different choices.

CreateWindow[
  DialogNotebook[DynamicModule[{name, activity, fauxDB, dbRow},
    fauxDB = {<|"name" -> "Bill", 
       "activities" -> {"Running", "Reading"}|>, <|"name" -> "Susan", 
       "activities" -> {"Swimming", "Sleeping"}|>};
    Column@{TextCell["Name: "],
      PopupMenu[Dynamic[name], fauxDB[[All, "name"]]],
      TextCell["Activity: "],
      dbRow = Select[fauxDB, #[[name]] == Dynamic[name] &][[1]];
      PopupMenu[Dynamic[activity], dbRow[["activities"]]],
      ChoiceButtons[{"Enter", "Cancel"}, {DialogReturn[{
          Print[name, " ", activity];
          }]}]
      }]
   ]];

The code above doesn't work; how might one create a DialogNotebook with variable elements as I describe?

$\endgroup$
4
$\begingroup$

You can use DynamicWrapper or the second argument of Dynamic to take an action after something is done.

Additionaly let me reshape your dataset to association form: <|name1->activities1,...|>

CreateWindow[ DialogNotebook[ DynamicModule[
   {name, activity, fauxDB, dbRow}
   , 
   fauxDB = {
     <|"name" -> "Bill", "activities" -> {"Running", "Reading"}|>, 
     <|"name" -> "Susan", "activities" -> {"Swimming", "Sleeping"}|>
   };

   fauxDB = GroupBy[fauxDB, Key["name"] -> Key["activities"], First];

   name = First @ Keys @ fauxDB;

   dbRow = fauxDB[name];

   Column @ {
     TextCell["Name: "],
     PopupMenu[ Dynamic[name, (*now the important part*)
       {Automatic, (dbRow = fauxDB[name]; activity = First@dbRow) &}
       ], 
       fauxDB // Keys
     ],
     TextCell["Activity: "],
       (*additional dynamic to track dbRow changes, also important*)
     Dynamic @ PopupMenu[ Dynamic[activity], dbRow]
     ,
     ChoiceButtons[
      {"Enter", "Cancel"},
      {DialogReturn[{Print[name, " ", activity];}]}
      ]}
   ]]
 ]
$\endgroup$
  • $\begingroup$ Took a bit of fussing in my real application but a variation on this approach worked, thank you. Why did you reshape the dataset? I always separate fields for the sake of debugging and later maintenance. Am I missing something? $\endgroup$ – Michael Stern May 31 '16 at 20:38
  • $\begingroup$ @MichaelStern unless it's really big I like to use different representations of datasets depending of the context. Here fauxDB[name] is shorter/more readable than querying with Select. I'd say at the end it's a matter of taste. $\endgroup$ – Kuba May 31 '16 at 20:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.