# How to make DynamicModule work without an extra ENTER

I've been trying to learn more about DynamicModule (I do not use them, as I used Manipulate all the time).

After some time struggling with this, and reading everything I can about Dynamics, and lots of trials and errors, I gave up.

Any one can figure why this DynamicModule will initialize correctly and run ok, ONLY after I hit ENTER on the cell an extra time?

This is a problem, since when I saved it to a CDF and opened the CDF, it does not run, since it needs an ENTER to initialize, which is not possible to do in CDF.

DynamicModule[{max = Pi/4, plot = plotClass[Pi/4]},

Row[{
Dynamic[plot@set[max]],
Framed@Grid[{
{Slider[Dynamic[max], {.1, 2 Pi, .1}], Dynamic@max},
{Dynamic[plot@make[]], SpanFromLeft}
}
]
}
],
Initialization :> {
plotClass[$max_] := Module[{self, mymax}, self@set[v_] := mymax = v; self@make[] := Module[{x}, Plot[Sin[x], {x, 0, mymax}, PlotRange -> {{0, 2 Pi}, {-1, 1}}, ImageSize -> 200] ]; mymax =$max;
self
]
}
]


To see the problem, simply do

1. Paste the above into an empty cell (but do not hit ENTER yet)
2. close the kernel Evalution->Quit kernel
3. Hit ENTER on the cell. Now you'll see the plot
4. Now move the slider. You'll see that the plot does not update
5. Now hit ENTER one more time into the cell. Now moving the slider will update the plot
6. To reproduce, delete the output cell and go back to step 2.

So it needs one more ENTER to work. Another way to see this, is to save the notebook as CDF and open the CDF. You'll see it does not work.

I am sure I am doing something silly. But as I said, I just started learning DynamicModule.

The problem is with the evaluation with the Module in the Initialization section. It does not get defined without an extra ENTER for some reason. I tried many different way to define this Module, and they are failed. One extra ENTER is needed.

Mathematica 9.0.1, on windows 7.

-

I think that Mike has a point: it is always good to start with something simple. Here is a very simple example which shows the main problem you have: the Initialization-code is evaluated only after the body of the DynamicModule has been evaluated. This might be surprising considering its name but I think is in agreement with the documentation, which is somewhat vague about these details:

DynamicModule[{x = (Print[Date[] -> "local vars"]; Pause[0.1]; 0.5)},
Print[Date[] -> "body"]; Pause[0.1];
Row[{Slider[Dynamic[x]], Dynamic[x]}],
Initialization :> (Print[Date[] -> "initialization"]; Pause[0.1])
]


There is another problem with your construct that you have to take into account: When the output is still visible and you Quit the Kernel the Initialization-code of that still visible DynamicModule might be evaluated before anything of the shift-return-evaluation that will create the new output. This will in your case define plotClass, so that the new output will work from the beginning, but only if the old output was still visible (that is neither deleted nor scrolled out of sight). In combination the outcome will look almost random. To prevent this, it is better to define plot=plotClass[max] also in the Initialization-code: it's probably important to note that you do have access to the local variables of the DynamicModule there as well. This will also ensure that this definition is made when the DynamicModule is initialized without the shift-return-evaluation that did generate it...

Finally I think there is an additional potential source of errors in your code: with Dynamic[plot@set[max]] you are setting a variable from within a Dynamic evaluation. My experience is that with this you are asking for trouble as it is not defined whether this Dynamic will be evaluated before the one that will show the plot. Either way you might trigger additional (unneccessary) evaluations which might become a performance problem and in more complicated cases even create infinite recursions, hangups and crashes. It is much better to do all settings of variables in the second argument of the controler Dynamic, as here:

DynamicModule[{max = Pi/4., plot},
Row[{
Dynamic[NumberForm[N[plot@getMax[]], {4, 2}]],
Framed@Grid[{{
Slider[
Dynamic[max, (max = #; plot@setMax[max]) &], {.1, 2 Pi, .1}],
Dynamic[NumberForm[N@max, {4, 2}]]
}, {
Dynamic[plot@make[]], SpanFromLeft
}}]
}],
Initialization :> (
plotClass[$max_] := Module[{self, mymax}, self@setMax[v_] := mymax = v; self@getMax[] := mymax; self@make[] := Module[{x}, Plot[Sin[x], {x, 0, mymax}, PlotRange -> {{0, 2 Pi}, {-1, 1}}, ImageSize -> 200] ]; mymax =$max;
self
];
plot = plotClass[max];
)
]

-
 Thanks Albert. In one of my tried, I did try creating the plot object at the end of the Initialization section (this is what I do when using Manipulate as well). I did not use this, since I saw that plot inside DyanmicModule is not the same global plot used in the Initialization section. When I add Print[plot] at the very top of the DynamicModule, and the botton of the Initialization section, they print different names. Actually if remove the local plot from DynamicModule, your code will still work as is. screen shot: !Mathematica graphics .... – Nasser Feb 24 at 11:38 and on the console I see this: plot$1457 and plot$1467. So the plot which is actually being used is the global one (the one at the bottom of the Initialziation section. So your code will work now like this: !Mathematica graphics You see, I removed the local plot from inside DynamicModule, and it still works in CDF now. But using the global plot. But this is OK with me. At least it works. But I just wanted to say I tried this trick, but rejected it too quickly when I saw it is different object than the local plot. Thank you very much. – Nasser Feb 24 at 11:41 This might be surprising considering its name but I think is in agreement with the documentation, which is somewhat vague about these details Would you please have a reference where it says that the body of DynamicModule is evaluated BEFORE the Initialization section? I did actually notice that during one of the many tries (with lots of print statments), but I was baffled by it and thought I was doing something wrong or just a side effect of the print IO. One would expect something called Initialization to be evaluated first thing. But what do I know. – Nasser Feb 24 at 11:57 @nasser How about this sentence: When DynamicModule is first evaluated, initial assignments for local variables are made during the evaluation. Any setting for the Initialization option is evaluated only when the output of DynamicModule is displayed.  So, as the docs already stated earlier, variables are localized and initialized, the body is evaluated. It will be displayed after that. That's when the Initialization code will execute. – Sjoerd C. de Vries Feb 24 at 13:03 @SjoerdC.deVries great. Thanks! I got it now. it is all working well now. I am now converting a large demo I did with Manipulate to DynamicModule. DyanmicModule allow more flexibility. Manipulate makes somethings easier to set up but it was hard to do some other thing with it that I wanted to do. I think learning to use DynamicModule is worth it. The only thing is that the objects I am using remain global (the plot object in this example). I wanted them to be local to the DyanmicModule. But that is ok. Same problem was with Manipulate when using this setup actually. can't avoid it. – Nasser Feb 24 at 13:27
show 1 more comment

This is too long for a comment. I don't really have time to pull this code apart but if the objective is to learn DynamicModule wouldn't a simpler piece of code be a better start?

If you look at what variables have been created after the first ENTER this is a small sample of what you get

I think it would be best to pull your code apart and figure out why you are infinitely looping through variable creation.

Just extending my comment...

I was about to go to bed so didn't have time to figure it out last night. Nice answer from Albert. To get a feel for what happens after the first Shift+Enter wrap the thing in InputForm. What gave me a headache last night and led me to leave it was this:

This is what you get from Alberts code above

DynamicModule[{max = 0.7853981633974483, plot},
Row[{Dynamic[NumberForm[N[plot[getMax[]]], {4, 2}]],
Framed[Grid[{{Slider[Dynamic[max, (max = #1; plot[setMax[max]]) & ],
{0.1, 2*Pi, 0.1}], Dynamic[NumberForm[N[max], {4, 2}]]},
{Dynamic[plot[make[]]], SpanFromLeft}}]]}],
Initialization :> (plotClass[$max_] := Module[{self, mymax}, self[setMax[v_]] := mymax = v; self[getMax[]] := mymax; self[make[]] := Plot[Sin[x], {x, 0, mymax}, PlotRange -> {{0, 2*Pi}, {-1, 1}}, ImageSize -> 200]; mymax =$max; self]; plot = plotClass[max]; ),
DynamicModuleValues :> {}]


However last night when I did that with your code I got:

DynamicModule[{max = Pi/4, plot = plotClass[Pi/4]},
Row[{Dynamic[plot[set[max]]],
Framed[Grid[{{Slider[Dynamic[BoxFormRemapVariable[max, {0.1, 2*Pi, 0.1}],
BoxFormRemapValue[#1, max, {0.1, 2*Pi, 0.1}] & ], {0., 61.83185307179586,
1.}], Dynamic[max]}, {Dynamic[plot[make[]]], SpanFromLeft}}]]}],
Initialization :> {plotClass[$max_] := Module[{self, mymax}, self[set[v_]] := mymax = v; self[make[]] := Module[{x}, Plot[Sin[x], {x, 0, mymax}, PlotRange -> {{0, 2*Pi}, {-1, 1}}, ImageSize -> 200]]; mymax =$max; self]}, DynamicModuleValues :> {}]


...which was a WTF! moment because I have not come across BoxFormRemapVariable before. Has anyone else ever seen that before?

-
 I know basic DynamicModule, even thought I have not used them in demos before. So the basic stuff is covered. I needed to implement the same object based construct I use in Manipulate inside DynamicModule. I posted the most simple case of this construct. It is less than 20 lines or so. I posted the code to get help from experts to see what is wrong with it. I know already it is not working correctly. – Nasser Feb 24 at 11:19 I saw RemapValue` once, this is the link. But I don't know anything about it. – Szabolcs Feb 24 at 22:16 @Mike See my edit on how to put a backtick in inline code. This backtick notation isn't the luckiest for mma ... but then is there any character mma doesn't use? – Szabolcs Feb 24 at 22:17 thanks @Szabolcs – Mike Honeychurch Feb 24 at 22:55