Introduction to Dynamic

This tutorial describes the principles behind (RefLink[Dynamic, paclet:ref/Dynamic]), (RefLink[DynamicModule, paclet:ref/DynamicModule]), and related functions, and goes into detail about how they interact with each other and with the rest of the Wolfram Language.

These functions are the foundation of the higher-level function (RefLink[Manipulate, paclet:ref/Manipulate]) that provides a simple yet powerful way of creating a great many interactive examples, programs, and Demonstrations, all in a very convenient, though relatively rigid, structure. If that structure solves the problem at hand, you need look no further than (RefLink[Manipulate, paclet:ref/Manipulate]) and you do not need to read this tutorial. However, do continue with this tutorial if you want to build a wider range of structures, including complex user interfaces.

The Fundamental Principle of Dynamic

Ordinary Wolfram Language sessions consist of a series of static inputs and outputs, which form a record of calculations done in the order in which they were entered.

Evaluate each of these four input cells one after the other:

x=5;

(x^2)

x=7;

(x^2)

The first output still shows the value from when x was 5, even though it is now 7. This is, of course, very useful, if you want to see a history of what you have been doing. However, you may often want a fundamentally different kind of output, one that is automatically updated to always reflect its current value. This new kind of output is provided by (RefLink[Dynamic, paclet:ref/Dynamic]).

Evaluate the following cell; note that the result will be 49 because the current value of x is 7:

Dynamic[(x^2)]

In fact it is generally the case that when you first evaluate an input that contains variables wrapped in (RefLink[Dynamic, paclet:ref/Dynamic]), you will get the same result as you would have without (RefLink[Dynamic, paclet:ref/Dynamic]). But if you subsequently change the value of the variables, the displayed output will change retroactively.

Evaluate the following cells one at a time, and note the change in the value displayed above:

x=9;

x=15;

x=10;

The first two static outputs are still 25 and 49 respectively, but the single dynamic output now displays 100, the square of the last value of x. (This sentence will, of course, become incorrect as soon as the value of x is changed again.)

There are no restrictions on the kinds of values that can go into a dynamic output. Just because x was initially a number does not mean it cannot become a formula or even a graphic in subsequent evaluations. This might seem like a simple feature, but it is the basis for a very powerful set of interactive capabilities.

Each time the value of x is changed, the dynamic output above is updated automatically. (You might need to scroll back to see it.)

x=Integrate[(1/(1-(y^3))),y];

x=Plot[Sin[x],{x,0,2Pi}];

x=0;

Basic dynamic expression.

Dynamic and Controls

(RefLink[Dynamic, paclet:ref/Dynamic]) is often used in connection with controls such as sliders and checkboxes. The full range of controls available in the Wolfram Language is discussed in "Control Objects"; here sliders are used to illustrate how things work. The principles of using (RefLink[Dynamic, paclet:ref/Dynamic]) with other controls is basically the same.

A slider is created by evaluating the (RefLink[Slider, paclet:ref/Slider]) function, in which the first argument is the position and the optional second argument specifies the range and step size, with the default range from 0 to 1 and the default step size 0.

This is a slider in a centered position:

Slider[0.5]

Click on the thumb and move it around. The thumb moves, but nothing else happens since the slider is not connected to anything.

This associates the position of the slider with the current value of the variable x. (This form is explained in more detail later.)

Slider[Dynamic[x]]

This creates a new dynamic output of x since the last one has probably scrolled off your screen by now:

Dynamic[x]

Drag the last slider around. As the slider moves, the value of x changes and the dynamic output updates in real time.

The slider also responds to changes in the value of x.

To see this, evaluate this line:

x=0.8;

You should see the slider jump, and the dynamic output of x change, simultaneously.

This creates another x slider:

Slider[Dynamic[x]]

Notice that if you move either of the two sliders you now have, the other one moves in "lock sync". Both are connected, dynamically and bidirectionally, to the current value of x.

Dynamic and Other Functions

(RefLink[Dynamic, paclet:ref/Dynamic]) and control constructs such as (RefLink[Slider, paclet:ref/Slider]) are in many ways just like any other functions in the Wolfram Language. They can occur anywhere in an output, in tables, and even inside typeset mathematical expressions. Wherever these functions occur, they carry with them the behavior of dynamically displaying or changing in real time the current value of the expression or variable they are linked to. (RefLink[Dynamic, paclet:ref/Dynamic]) is a simple building block, but the rest of the Wolfram Language turns it into a flexible tool for creating nimble, zippy, and often fun little interactive displays.

This makes a table of x sliders, which are updated in sync:

Table[Slider[Dynamic[x]],{4}]

You can combine a slider with a display of its current value in a single output:

{Slider[Dynamic[x]],Dynamic[x]}

The great power of (RefLink[Dynamic, paclet:ref/Dynamic]) lies in the fact that it can display any function of x just as easily:

{Slider[Dynamic[x]],Dynamic[Plot[Sin[10y x],{y,0,2Pi}]]}

Using integer-valued sliders, you can create dynamically updated algebraic expressions:

{Slider[Dynamic[x1],{1,10,1}],Dynamic[Expand[(((a+b))^x1)]]}

You can use dynamic expressions with (RefLink[Panel, paclet:ref/Panel]), (RefLink[Row, paclet:ref/Row]), (RefLink[Column, paclet:ref/Column]), (RefLink[Grid, paclet:ref/Grid]), and other formatting constructs:

Panel[Column[{Row[{Slider[Dynamic[x]],Dynamic[x]}],Dynamic[Plot[Sin[10y x],{y,0,2Pi}]]}]]

Notice that the last example resembles the output of (RefLink[Manipulate, paclet:ref/Manipulate]). This is no coincidence, because (RefLink[Manipulate, paclet:ref/Manipulate]) in fact produces a combination of (RefLink[Dynamic, paclet:ref/Dynamic]), controls, and formatting constructs, not fundamentally different from what you can do yourself using these lower-level functions.

Localizing Variables in Dynamic Output

Here is another copy of a slider connected to a simple plot:

{Slider[Dynamic[x]],Dynamic[Plot[Sin[10y x],{y,0,2Pi}]]}

This is a slider connected to another function:

{Slider[Dynamic[x]],Dynamic[Plot[Tan[10y x],{y,0,2Pi}]]}

If you have both these outputs visible and drag either slider, you will notice that they are communicating with each other. Move the slider in one example, and the other example moves too. This is because you are using the global variable x in both examples. Although this can be very useful in some situations, most of the time you would probably be happier if these two sliders could be moved independently. The solution is a function called (RefLink[DynamicModule, paclet:ref/DynamicModule]).

Localizing and initializing variables for (RefLink[Dynamic, paclet:ref/Dynamic]) objects.

(RefLink[DynamicModule, paclet:ref/DynamicModule]) has arguments identical to (RefLink[Module, paclet:ref/Module]) and is similarly used to localize and initialize variables, but there are important differences in how they operate.

Here are the same two examples with "private" values of x:

DynamicModule[{x=.5},{Slider[Dynamic[x]],Dynamic[Plot[Sin[10y x],{y,0,2Pi}]]}]

Notice that these two examples now work independently of each other:

DynamicModule[{x=.5},{Slider[Dynamic[x]],Dynamic[Plot[Tan[10y x],{y,0,2Pi}]]}]

Multiple instances of (RefLink[DynamicModule, paclet:ref/DynamicModule]) can be placed in a single output, and they maintain separate values of the variables associated with their respective areas in the output:

{DynamicModule[{x=.5},{Slider[Dynamic[x]],Dynamic[Plot[Sin[10y x],{y,0,2Pi}]]}],
DynamicModule[{x=.5},{Slider[Dynamic[x]],Dynamic[Plot[Tan[10y x],{y,0,2Pi}]]}]}

You might be tempted to use (RefLink[Module, paclet:ref/Module]) in place of (RefLink[DynamicModule, paclet:ref/DynamicModule]), and in fact this would appear to work at first. However, it is not a good idea for several reasons, which are discussed in more detail in "Advanced Dynamic Functionality".

(RefLink[DynamicModule, paclet:ref/DynamicModule]) does its work in the front end, not in the kernel. It remains unchanged by evaluation, and when formatted as output, it creates an invisible object, embedded in the output expression that handles the localization. As long as that space of output remains in existence (i.e. is not deleted), the invisible object representing the (RefLink[DynamicModule, paclet:ref/DynamicModule]) will maintain the values of the variables, allowing them to be used in subsequent evaluations of (RefLink[Dynamic, paclet:ref/Dynamic]) expressions within the scope (area) of the (RefLink[DynamicModule, paclet:ref/DynamicModule]).

If you save a notebook containing a (RefLink[DynamicModule, paclet:ref/DynamicModule]), close that notebook, then later reopen it in a new Wolfram System session, the values of all the local variables will still be preserved and the sliders inside the (RefLink[DynamicModule, paclet:ref/DynamicModule]) will be in the same positions. This will not be the case with sliders linked to global variables (like the earliest examples in this tutorial), nor with sliders linked to variables localized with (RefLink[Module, paclet:ref/Module]) instead of (RefLink[DynamicModule, paclet:ref/DynamicModule]). Such variables store their values in the current Wolfram Language kernel session, and they are lost as soon as you quit the Wolfram System.

In addition to localizing variables to particular regions of output, (RefLink[DynamicModule, paclet:ref/DynamicModule]) provides options to automatically initialize function definitions when an expression containing a (RefLink[DynamicModule, paclet:ref/DynamicModule]) is opened, and to clean up values when the expression is closed or deleted. More details are found in (RefLink[DynamicModule, paclet:ref/DynamicModule]).

The Second Argument of Dynamic

Dynamic connections are by default bidirectional. Sliders connected to a variable move together because they both reflect and control the value of the same variable. When you drag a slider thumb, the system constructs and evaluates expressions of the form expr=new, where expr is the expression given in the first argument to (RefLink[Dynamic, paclet:ref/Dynamic]) and new is the proposed new value determined by where you have dragged the slider thumb. If the assignment can be done, the new value is accepted. If the assignment fails, the slider will not move.

These two sliders move in opposite directions when you move the first one. However, trying to move the second slider gives an error because you cannot assign a new value to the expression 1-x:

DynamicModule[{x=0},{Slider[Dynamic[x]],Slider[Dynamic[1-x]]}]

You can keep an arbitrary expression in the first argument of (RefLink[Dynamic, paclet:ref/Dynamic]), but change the dynamically executed evaluation by using the optional second argument. This is a convenient way to specify "inverse functions" that update the values of variables in the first arguments. The Wolfram Language does not attempt to deduce such inverse functions automatically from the first argument of (RefLink[Dynamic, paclet:ref/Dynamic]); you have to supply one yourself.

Inverse functions.

This specifies how the value of x is to be updated and makes the second slider interactive. You can move either slider and the other slider responds by moving in the opposite direction:

DynamicModule[{x=0},{Slider[Dynamic[x]],Slider[Dynamic[1-x,(x=1-#)&]]}]

Now the dynamically executed expression in the second slider is the pure function (x=1-#)&, which is given the proposed new value in #. Note that the function is responsible for actually doing the assignment to whatever variable you want to change; you cannot just say (1-#)& if you want to change x.

The ability to interpose your own arbitrary function between the mouse position and the state of the Wolfram System is very powerful, and you can use it for purposes beyond simple inverse functions. The function given in the second argument is effectively free to do anything it wants.

This defines "detents" that snap the slider to integer values if the thumb is within a certain tolerance of a round number:

DynamicModule[{x=0},{Slider[Dynamic[x,If[Abs[#-Round[#]]<0.1,x=Round[#],x=#]&],{0,5}],Dynamic[x]}]

This makes the variable take on rational numbers (integer fractions) instead of decimals:

DynamicModule[{x=0},{Slider[Dynamic[x,(x=Rationalize[#])&],{0,5}],Dynamic[x]}]

For complete control over the tracking behavior, it is possible to specify separate functions that are called at the start, middle, and end of a mouse click on the slider thumb. If you are familiar with conventional user-interface programming, you will recognize these as separate, high-level event functions for the mouse-down, mouse-drag, and mouse-up events.

This changes the background color while the click-and-drag operation is underway:

DynamicModule[{x=0,bg=RGBColor[0,0,1]},Style[Slider[Dynamic[x,
{(bg=RGBColor[1,0,0])&,
(x=#)&,
(bg=RGBColor[0,0,1])&}]],Background->Dynamic[bg]]]

The second argument of (RefLink[Dynamic, paclet:ref/Dynamic]) also lets you restrict the movement of a slider and effectively implement geometric constraints.

You can only move the thumb of this (RefLink[Slider2D, paclet:ref/Slider2D]) along a circle:

DynamicModule[{pt={1,0}},Slider2D[Dynamic[pt,(pt=#/Norm[#])&],{-1,1},Exclusions->{0,0}]]

Where Should Dynamic Be Placed in an Expression?

The fundamental behavior of (RefLink[Dynamic, paclet:ref/Dynamic]) is to build a copy of the input expression into the output cell. To be more specific, (RefLink[Dynamic, paclet:ref/Dynamic]) has the attribute (RefLink[HoldFirst, paclet:ref/HoldFirst]) and remains unchanged by evaluation.

The result of evaluating (RefLink[Dynamic, paclet:ref/Dynamic])[x+y] is (RefLink[Dynamic, paclet:ref/Dynamic])[x+y], which you can see by examining the (RefLink[InputForm, paclet:ref/InputForm]) representation of the output:

Dynamic[x+y]//InputForm

You do not see (RefLink[Dynamic, paclet:ref/Dynamic]) in ordinary output because, when formatted for display in the front end, (RefLink[Dynamic, paclet:ref/Dynamic])[x+y] is represented by an object that contains a copy of the unevaluated input (x+y), but displays as the evaluated value of that expression. The (RefLink[Dynamic, paclet:ref/Dynamic]) wrapper is still present in the output, but it is invisible.

Because (RefLink[Dynamic, paclet:ref/Dynamic]) does its work entirely in the front end, you cannot use it inside functions that need to access the value of an expression in order to do their work.

For example, this works:

DynamicModule[{x},{Slider[Dynamic[x],{1,5}],Dynamic[Plot[Sin[x i],{i,0,2Pi}]]}]

But this does not:

DynamicModule[{x},{Slider[Dynamic[x],{1,5}],Plot[Sin[Dynamic[x]i],{i,0,2Pi}]}]

The (RefLink[Plot, paclet:ref/Plot]) command needs to have specific numerical values for x to make a plot, but the (RefLink[Dynamic, paclet:ref/Dynamic])[x] inside the function being plotted does not evaluate into anything in the kernel. It remains inert as (RefLink[Dynamic, paclet:ref/Dynamic])[x], preventing the (RefLink[Plot, paclet:ref/Plot]) command from doing anything sensible.

Another way to look at it is that the expression inside a (RefLink[Plot, paclet:ref/Plot]) command does not appear directly anywhere in the output. (RefLink[Dynamic, paclet:ref/Dynamic]) is a formatting function that does its work in the front end, not in the kernel, so if it is used in a way where it will never be placed as output, it is probably a mistake.

When combining (RefLink[Dynamic, paclet:ref/Dynamic]) with controls, it is particularly important to get the (RefLink[Dynamic, paclet:ref/Dynamic]) in the right place.

This example works as expected; move the slider and the value of x changes:

DynamicModule[{x=0.5},{Slider[Dynamic[x]],Dynamic[x]}]

This example looks good at first, but if you move the slider, x does not change:

DynamicModule[{x=0.5},{Dynamic[Slider[x]],Dynamic[x]}]

That is because when the (RefLink[Dynamic, paclet:ref/Dynamic]) wrapped around (RefLink[Slider, paclet:ref/Slider])[x] evaluates its contents, the value of x is substituted, and the result is a slider whose first argument is a specific number, with no trace of the variable name left. The slider in this case is a dynamic display of a static slider.

What is needed is a static slider, which contains within it a dynamic reference to the value of the variable. In the case of controls, there is a simple rule for where to put the (RefLink[Dynamic, paclet:ref/Dynamic]). The first argument of any control function, such as (RefLink[Slider, paclet:ref/Slider]), (RefLink[Checkbox, paclet:ref/Checkbox]), or (RefLink[PopupMenu, paclet:ref/PopupMenu]), will almost always be (RefLink[Dynamic, paclet:ref/Dynamic])[var].

Beyond these cases where (RefLink[Dynamic, paclet:ref/Dynamic]) will not work in a particular position, there is often a great deal of flexibility about where to place (RefLink[Dynamic, paclet:ref/Dynamic]). It is often used as the outermost function in an input expression, but this is by no means necessary, and in more sophisticated applications, (RefLink[Dynamic, paclet:ref/Dynamic]) is usually used deeper in the expression and can even be nested.

This displays a table of 10 copies of the value of x:

Dynamic[Table[x,{i,10}]]

(RefLink[Dynamic, paclet:ref/Dynamic]) is wrapped around the whole expression, so evaluation of the (RefLink[Table, paclet:ref/Table]) command is delayed until the output is displayed in the notebook. Any time the value of x is changed, the (RefLink[Table, paclet:ref/Table]) command will be reevaluated.

The output from this example looks exactly the same:

Table[Dynamic[x],{i,10}]

But in this case the (RefLink[Table, paclet:ref/Table]) command is evaluated immediately, generating a list of 10 separate (RefLink[Dynamic, paclet:ref/Dynamic]) expressions, each of which evaluates x separately after the overall result has been placed in the notebook.

When x is changed, the first example sends a single request to the kernel to get the value of (RefLink[Table, paclet:ref/Table])[x,{i,10}], while the second example sends 10 separate requests to the kernel to get the value of x. It might seem that the first example is obviously more efficient, and in this case it is. However, you should also avoid the other extreme: wrapping too many things into a single (RefLink[Dynamic, paclet:ref/Dynamic]), which can also be inefficient.

This initializes x and y to set up a new slider connected to the value of x:

x=0.5;

y=Plot3D[Sin[n m],{n,0,4},{m,0,4}];

Slider[Dynamic[x]]

This is a tab view with two groups of dynamic expressions, both showing the dynamic values of x (a simple number) and y (a 3D plot):

TabView[{{Dynamic[x],Dynamic[y]},Dynamic[{x,y}]}]

Drag the slider around, and note that the value of x in the first tab updates quite rapidly. On most computers it will be essentially instantaneous. However, updates are more sluggish in the second tab. Each individual (RefLink[Dynamic, paclet:ref/Dynamic]) expression keeps track (quite carefully) of exactly when it might need to be reevaluated in order to remain up to date. In the second tab, the output is forcing the whole expression {x,y}, including the large, slow 3D plot, to be reevaluated every time the value of x changes. By using two separate (RefLink[Dynamic, paclet:ref/Dynamic]) expressions in the first tab, you allow the value of x to be updated without needing to also reevaluate y, which has not actually changed. (You may want to delete the last output before proceeding, as it will slow down any examples containing the global x as long as it is visible on screen.)

It is hard to make blanket statements about where (RefLink[Dynamic, paclet:ref/Dynamic]) should be placed in every case, but generally speaking if you are building a large, complex output where only small parts of it will change, the (RefLink[Dynamic, paclet:ref/Dynamic]) should probably be wrapped just around those parts. On the other hand, if all or most of the output is going to change in response to a single variable changing its value, then it is probably best to wrap (RefLink[Dynamic, paclet:ref/Dynamic]) around the whole thing.

Dynamic in Options

(RefLink[Dynamic, paclet:ref/Dynamic]) can be used on the right-hand side of options, in those cases where the option value will be transmitted to the front end before being used. This is a somewhat subtle distinction related to the discussion in "Where Should Dynamic Be Placed in an Expression?".

An option like (RefLink[PlotPoints, paclet:ref/PlotPoints]) in plotting commands cannot have (RefLink[Dynamic, paclet:ref/Dynamic]) on the right-hand side, because the plotting command needs to know a specific numerical value before the plot can be generated. Remember that (RefLink[Dynamic, paclet:ref/Dynamic]) has the effect of delaying evaluation until the expression reaches the front end, and in the case of (RefLink[PlotPoints, paclet:ref/PlotPoints]), that is too late since the value is needed right away. On the other hand, options to functions that do their work in the front end can usually, and usefully, accept (RefLink[Dynamic, paclet:ref/Dynamic]) in their option values.

For example, you can control the size of a block of text in two ways.

(RefLink[Dynamic, paclet:ref/Dynamic]) can be wrapped around a whole (RefLink[Style, paclet:ref/Style]) expression:

h=12;

{Slider[Dynamic[h],{6,100}],Dynamic[Style["Some Text",FontSize->h]]}

Or (RefLink[Dynamic, paclet:ref/Dynamic]) can be only in the (RefLink[FontSize, paclet:ref/FontSize]) option value:

{Slider[Dynamic[h],{6,100}],Style["Some Text",FontSize->Dynamic[h]]}

There are two potential advantages to putting the (RefLink[Dynamic, paclet:ref/Dynamic]) in the option value. First, suppose the dynamically regenerated expression is very large, for example, the entire document. It is inefficient to retransmit it from the kernel to the front end every time the font size is changed, as is necessary if (RefLink[Dynamic, paclet:ref/Dynamic]) encloses the whole expression.

Second, the output of a (RefLink[Dynamic, paclet:ref/Dynamic]) expression is not editable (since it is liable to be regenerated at any moment), which makes the output of the first example noneditable. But the text in the second example can be edited freely since it is ordinary static output: only the option value is dynamic.

Dynamic option values can be also set in the Option Inspector. They are allowed at the cell, notebook, or global level, and in stylesheets. (Note, however, that if you set a dynamic option value in a position where the value will be inherited by many cells, for example in a stylesheet, there can be a significant impact on performance.)

You can set dynamic option values through (RefLink[SetOptions, paclet:ref/SetOptions]), as well:

x=0;

SetOptions[EvaluationNotebook[],Background->Dynamic[Hue[x]]]

Having linked the background color of the notebook to the global variable x, it can now be controlled by a slider or by a program:

Slider[Dynamic[x]]

Of course, it is good to be able to return to normal:

SetOptions[EvaluationNotebook[],Background->Inherited]

Dynamic and Infinite Loops

If you are not careful, you can easily throw (RefLink[Dynamic, paclet:ref/Dynamic]) into an infinite loop.

This counts upward as fast as possible for as long as it remains on screen:

DynamicModule[{x=1},Dynamic[x=x+1]]

This is not a bug (but delete the above output if it is distracting you to have it there).

Because the output is updated and the screen redrawn after each cycle of an infinite loop, it is actually quite a useful thing to be able to do. Generally speaking, the system will remain responsive to typing, evaluation, and so on, even as the infinitely updating (RefLink[Dynamic, paclet:ref/Dynamic]) zips along.

It is also useful to make such a self-triggering (RefLink[Dynamic, paclet:ref/Dynamic]) that stops changing at some point.

This is a "droopy" slider that always drops back to zero no matter what you drag it to:

DynamicModule[{x=1},{VerticalSlider[Dynamic[x]],Dynamic[x=Max[0,x-0.01]]}]

If you have a CPU monitor running, you will see that while the slider is dropping there is a small load on the CPU (for redrawing the screen, primarily), but once it reaches zero, the load drops to nothing. The dynamic tracking system has noticed that the value of x did not change: therefore, further updating is not necessary until someone changes the value of x again (e.g. when you click on the slider). "Advanced Dynamic Functionality" describes in more detail how the dynamic tracking system works.

A Good Trick to Know

Because it has the attribute (RefLink[HoldFirst, paclet:ref/HoldFirst]), (RefLink[Dynamic, paclet:ref/Dynamic]) does not evaluate its first argument. This is fundamental to the workings of (RefLink[Dynamic, paclet:ref/Dynamic]), but it can lead to a somewhat unexpected behavior.

For example, suppose you have a list of numbers you wish to be able to modify by creating one slider to control each value.

This creates the list and a dynamic display of its current value:

data={.1,.5,.3,.9,.2};

Dynamic[data]

This attempts to make a table of sliders, one for each element of the list, using list[[i]] to access the individual members:

Table[Slider[Dynamic[data[[i]]]],{i,5}]

Surprisingly, this does not work! You can see an error indication around the sliders, they cannot be moved, and the dynamic output above never changes. You might even jump to the conclusion that part extraction syntax cannot be used in this way with controls. Nothing could be further from the truth.

The problem is that the variable i was given a temporary value by the (RefLink[Table, paclet:ref/Table]) command, but that value was never used, because (RefLink[Dynamic, paclet:ref/Dynamic]) is (RefLink[HoldFirst, paclet:ref/HoldFirst]).

Looking at the (RefLink[InputForm, paclet:ref/InputForm]) of the table of sliders reveals the problem:

Table[Slider[Dynamic[data[[i]]]],{i,5}]//InputForm

What is needed is to do a replacement of the variable i with its temporary value, even inside held expressions.

This can be done with (RefLink[/., paclet:ref/ReplaceAll]) or with the somewhat peculiar but convenient idiomatic form demonstrated here:

Table[With[{i=i},Slider[Dynamic[data[[i]]]]],{i,5}]

This output shows that (RefLink[Dynamic, paclet:ref/Dynamic]) does in fact work perfectly with part extraction syntax, a very useful property.

Slow Evaluations inside Dynamic

(RefLink[Dynamic, paclet:ref/Dynamic]) wrapped around an expression that will take forever, or even more than just a few seconds, to finish evaluating is a bad thing.

If you evaluate this example, you will have to wait about five seconds before seeing the output (RefLink[$Aborted, paclet:ref/$Aborted]):

Dynamic[While[True]]

During the wait for the (RefLink[Dynamic, paclet:ref/Dynamic]) output to evaluate, the front end is frozen, and no typing or other action is possible. Because updating of ordinary dynamic output locks up the front end, it is important to restrict the expressions you put inside (RefLink[Dynamic, paclet:ref/Dynamic]) to things that will evaluate relatively quickly (preferably, within a second or so). Fortunately computers, and the Wolfram System, are fast, so a wide range of functions, including complex 2D and 3D plots, can easily be evaluated in a fraction of a second.

To avoid locking up the front end for good, dynamic evaluations are internally wrapped in (RefLink[TimeConstrained, paclet:ref/TimeConstrained]), with a timeout value of, by default, five seconds. (This can be changed with the (RefLink[DynamicEvaluationTimeout, paclet:ref/DynamicEvaluationTimeout]) option.) In certain extreme cases, (RefLink[TimeConstrained, paclet:ref/TimeConstrained]) can fail to abort the calculation, in which case the front end will, a few seconds later, put up a dialog box allowing you to terminate dynamic updating until the offending output has been deleted.

Fortunately there is an alternative if you need to have something slow in a (RefLink[Dynamic, paclet:ref/Dynamic]). The option (RefLink[SynchronousUpdating, paclet:ref/SynchronousUpdating])->(RefLink[False, paclet:ref/False]) allows the dynamic to be evaluated in a way that does not lock up the front end. During evaluation of such an asynchronous (RefLink[Dynamic, paclet:ref/Dynamic]), the front end continues operating as usual, but the main Shift+MacOSXReturnEnter evaluation queue is occupied evaluating the (RefLink[Dynamic, paclet:ref/Dynamic]), so further Shift+MacOSXReturnEnter evaluations will wait until the (RefLink[Dynamic, paclet:ref/Dynamic]) finishes. (Normal synchronous (RefLink[Dynamic, paclet:ref/Dynamic]) evaluations do not interfere with Shift+MacOSXReturnEnter evaluations.)

Evaluate this example, and you will see a gray placeholder rectangle for about 10 seconds, after which the result will be displayed:

Dynamic[{DateList[],Pause[10];DateList[]},SynchronousUpdating->False]

Importantly, during that 10-second pause you are free to continue working on other things in the front end.

"Advanced Dynamic Functionality" gives more details about the differences between synchronous and asynchronous dynamic evaluations. In general, you should not plan to use asynchronous ones unless it is absolutely necessary. They do not update as quickly, and can interact in a very surprising, though not technically incorrect, way with controls and other synchronous evaluations.

Further Reading

The implementation details behind (RefLink[Dynamic, paclet:ref/Dynamic]) and (RefLink[DynamicModule, paclet:ref/DynamicModule]) are worth understanding if you plan to use complex constructions, particularly those involving nested (RefLink[Dynamic, paclet:ref/Dynamic]) expressions. This is discussed in "Advanced Dynamic Functionality".