While Initialization
is a useful option, it is only evaluated when the body of the DynamicModule
is displayed on screen. See some explanation on the evaluation sequence here.
With DynamicModule
I've constructed a TestPackage`
for this case, it contains the globally exported variable $Test
, with a value of 123. The following example shows that the package is not loaded (note that you have to clear dynamic content and variables (e.g. restart kernel) for each example below to start from a clear state of memory):
DynamicModule[{}, $Test, Initialization :> (Needs["TestPackage`"])]
$Test
It doesn't work with an explicit TestPackage`$Test
call either indicating that $Test
(and thus the body) is evaluated before the Initialization
code. This is somewhat contraintuitive, as one expects the initialization code to be evaluated before anything else. I should note here that the package is loaded, it is just loaded too late. Any later cells calling for $Test
return the correct value though. One way to overcome this in the given setup is to use the explicit name of $Test
in a dynamic output, which updates the unrecognized $Test
output when the package is finally loaded during evaluation:
DynamicModule[{}, Dynamic[TestPackage`$Test], Initialization :> Needs["TestPackage`"])]
123
The second example is even more strange. While the package loading code is included in the body, $Test
is still not recognized:
DynamicModule[{}, Needs["TestPackage`"]; $Test]
Using the explicit name of the variable helps here, indicating that parsing (done before evaluation) causes $Test
to be a local variable that is not recognized as TestPackage`$Test
:
DynamicModule[{}, Needs["TestPackage`"]; TestPackage`$Test]
123
Of course the easiest way is:
Needs["TestPackage`"];
DynamicModule[{}, $Test]
123
Update
And the Wolfram way is (see this conference material):
"Can be solved by two Needs[]
statements...one to fulfill Shift+Enter
evaluation and one to fulfill Dynamic
evaluation. Note that this is
only an issue because of $ContextPath
. Any other initialization code
could have safely appeared one time inside of Initialization
."
Needs["TestPackage`"];
DynamicModule[{}, Dynamic[$Test], Initialization :> Needs["TestPackage`"])]
123
With Manipulate
Following the Wolfram way, one needs the outer package loading, but in Manipulate
, SaveDefinitions
works correctly grabbing the definition of $Test
from the package:
Needs["TestPackage`"];
Manipulate[$Test, {$Test, None}, SaveDefinitions -> True]
123
With Dynamic
According to the above examples, with Dynamic
(each cell should be evaluated in a fresh kernel):
Dynamic[$Test, Initialization :> (Needs["TestPackage`"])]
Global`$Test
Dynamic[TestPackage`$Test, Initialization :> (Needs["TestPackage`"])]
123
Dynamic[Needs["TestPackage`"]; $Test]
Global`$Test
Dynamic[Needs["TestPackage`"]; TestPackage`$Test]
123