Adding reference type arguments, manipulating the value of template arguments, and binding an event.
Now let's try to manipulate the values of the template arguments "period", "feq" and "pause" in the templates/blocks/planet.tmpl+earth subpattern.
To do this, we will use reference arguments that are created by the fcf.argRef() function; when accessing this type of argument, not a direct read or write of the value is performed, but access to the data that was indicated when the argument was created.
First, we'll create in the main template :templates/blocks/planet.tmpl instances of the "period", "feq" and "pause" arguments with slightly modified values to make sure our mechanism works.
:templates/blocks/planet.tmpl file:
...
//~ARGUMENTS
{
fcfStyleInner: fcf.argVal("display: block; overflow: hidden; width: @{{args.width}}@; height: @{{args.height}}@"),
width: "100%",
height: "300px",
starsCount: 100,
stars: fcf.argProg(),
feq: 5,
period: 2,
pause: false,
}
...
And pass these values to the templates templates/blocks/planet.tmpl+earth. But not as a direct value, but as a reference argument. To do this, let's edit the template again :templates/blocks/planet.tmpl.
:templates/blocks/planet.tmpl file:
...
//~TEMPLATE
<div class="planet-container">
<div class="star-container">
%{{ for(let i = 0; i < args.stars.length; ++i) { }}%
<div
class="star"
style="left:@{{args.stars[i].left}}@%; top: @{{args.stars[i].top}}@%; animation-duration: @{{args.stars[i].duration}}@s; animation-delay: @{{args.stars[i].delay}}@s;"></div>
%{{ } }}%
</div>
<div class="planet-sun-container">
<div class="planet-sun-container-item">
<div class="planet-sun"></div>
</div>
</div>
@{{ render.template("+earth", {period: fcf.argRef("period"), feq: fcf.argRef("feq"), pause: fcf.argRef("pause") }); }}@
</div>
...
Now, if we change the values in the main template while the application is running, the arguments of the subpattern will also change.
To dynamically change the template arguments, we would use the integer value editor template @controls:int-edit from the fcfControls package.
Let's add one more "controls" sub-template, in which we will place the controls.
End of :templates/blocks/planet.tmpl file
...
//~OPTIONS controls
{
autoUpdate: true,
}
//~ARGUMENTS controls
{
fcfClassInner: "planet-controls-container",
}
//~TEMPLATE controls
<p>
<div class="planet-title-control">!{{Period}}!: </div>@{{ render.template("@controls:int-edit", {value: fcf.argRef("period"), min: 1, width: 80})}}@
</p>
<p>
<div class="planet-title-control">!{{Frequency}}!: </div>@{{ render.template("@controls:int-edit", {value: fcf.argRef("feq"), min: 1, width: 80})}}@
</p>
<p>
<div
class="planet-play-control"
fcfEventClick="wrapper.setArg('pause', !wrapper.getArg('pause'))"
>
@{{ args.pause ? ` >>> ${fcf.t("Play")} <<<` : `>>> ${fcf.t("Pause")} <<<` }}@
</div>
</p>
And we will execute the inference of our new subpattern by passing references to the arguments that we will manipulate.
:templates/blocks/planet.tmpl file:
...
//~TEMPLATE
<div class="planet-container">
<div class="star-container">
%{{ for(let i = 0; i < args.stars.length; ++i) { }}%
<div
class="star"
style="left:@{{args.stars[i].left}}@%; top: @{{args.stars[i].top}}@%; animation-duration: @{{args.stars[i].duration}}@s; animation-delay: @{{args.stars[i].delay}}@s;"></div>
%{{ } }}%
</div>
<div class="planet-sun-container">
<div class="planet-sun-container-item">
<div class="planet-sun"></div>
</div>
</div>
@{{ render.template("+earth", {period: fcf.argRef("period"), feq: fcf.argRef("feq"), pause: fcf.argRef("pause") }); }}@
@{{ render.template("+controls", {period: fcf.argRef("period"), feq: fcf.argRef("feq"), pause: fcf.argRef("pause") }); }}@
</div>
...
If everything is done correctly, then in the browser we will see an almost finished application. But let's figure out what was executed in the +controls subpattern
To manipulate the "feq" and "period" values, we used an editor template for the integer type (template @controls:int-edit). We passed a link as the main argument "value", and also limited the minimum input value by the min argument to 1. And for beauty, set its width to 80 pixels.
Handling events in the template body
Now let's look at managing the state of the pause argument. Its value is executed directly in the DOM handler of the click event. The framework can use event handling attributes that start with the fcfEvent prefix followed by the DOM event name. This mechanism is made for convenience, since objects of the template itself wrapper, the owner of the templateparent and of course the event object itself.
In the fcfEventClick event handler, we simply reverse the "pause" argument. To do this, use the methods wrapper.getArg() and wrapper.setArg()
The Pause/Play caption is displayed in the @{{ }}@ output construct using the translation into the user's language. To do this, use the fcf.t() function.
Now you can return the "period" and "feq" arguments to their normal values.
:templates/blocks/planet.tmpl file:
...
//~ARGUMENTS
{
fcfStyleInner: fcf.argVal("display: block; overflow: hidden; width: @{{args.width}}@; height: @{{args.height}}@"),
width: "100%",
height: "300px",
starsCount: 100,
stars: fcf.argProg(),
feq: 60,
period: 10,
pause: false,
}
...
Run the application in a browser and check how the values of the template arguments change.