JavaScript Framework fairy support js
Template

String

Let's change index.html and index.js to the following.

index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>
sample
</title>
<script id="fs-js" src="http://localhost:8000/js/fairysupport.min.js" data-page-root="http://localhost:8000/page"></script>
</head>
<body>
    <div data-obj="obj"></div>
    <div><button data-name="sample">sample</button></div>
</body>
</html>
index.js
export class Index {

    constructor() {
    }

    sample_click(event) {
        $f.loadStringTemplate(this.obj, this.template(), {'key1': '<input type="text">', 'key2': {'val1': 2}, 'key3': {"key1": "str1", "key2": "str2", "key3": "str3", "key4": "str4", "key5": "str5"}})
        .then(this.success.bind(this))
        .catch(this.error.bind(this));
    }

    sample2_input(event) {
        this.obj2.textContent = event.target.value;
    }

    success(nodeList) {
        alert("success");
    }

    error(exception) {
        alert("error");
        console.error(exception);
    }

    template() {
        return `
            <div>--data-text--</div>
            <div data-text='v.key1'></div>
            <div data-text='v.key1' data-tag='hidden'></div>

            <div>--data-html--</div>
            <div data-html='v.key1'></div>

            <div>--script--</div>
            <script data-load-only='true'>
                l.var = 1 + 2;
            </script>
            <div data-text='l.var'></div>

            <div>--data-attr--</div>
            <script data-load-only='true'>
                l.attr = {"style": "color: white; background-color: black;", "title" : "sample"};
            </script>
            <div data-attr='l.attr'>data-attr</div>
            <div data-attr='{"style": "color: white; background-color: black;", "title" : "sample"}'>data-attr</div>

            <div>--data-prop--</div>
            <script data-load-only='true'>
                l.prop = {"style": {"color" : "white", "backgroundColor": "black"}, "title" : "sample"};
            </script>
            <div data-prop='l.prop'>data-prop</div>
            <div data-prop='{"style": {"color" : "white", "backgroundColor": "black"}, "title" : "sample"}'>data-prop</div>

            <div>--data-if--</div>
            <div data-if='v.key2.val1 === 1'>
                v.key2.val1 === 1
            </div>
            <div data-elseif='v.key2.val1 === 2'>
                v.key2.val1 === 2
            </div>
            <div data-else=''>
                else
            </div>

            <div>--data-for--</div>
            <div data-for-start='l.i = 0' data-for-end='l.i < 10' data-for-step='l.i++'>
                <span data-if='l.i === 3' data-continue='1' data-tag='hidden'></span>
                <span data-if='l.i === 6' data-break='1' data-tag='hidden'></span>
                <div data-text='l.i'></div>
            </div>

            <div>--data-foreach--</div>
            <div data-foreach='v.key3' data-foreach-key='arrKey' data-foreach-value='arrVal'>
                <span data-if='l.arrVal === "str2"' data-continue='1' data-tag='hidden'></span>
                <span data-if='l.arrVal === "str4"' data-break='1' data-tag='hidden'></span>
                <span data-text='l.arrKey'></span>
                <span>:</span>
                <span data-text='l.arrVal'></span>
            </div>

            <div>--data-while--</div>
            <script data-load-only='true'>
                l.whileCount = -1;
            </script>
            <div data-while='l.whileCount < 8'>
                <script data-load-only='true'>
                    l.whileCount++;
                </script>
                <div data-if='l.whileCount === 3' data-continue='1' data-tag='hidden'></div>
                <div data-if='l.whileCount === 6' data-break='1' data-tag='hidden'></div>
                <div data-text='l.whileCount'></div>
            </div>

            <input data-name='sample2' type='text'>
            <div data-obj='obj2'></div>
        `;
    }

}

Let's run it and click the sample button.
The value of the third argument of $f.loadStringTemplate is embedded in the return value of the template method of index.js and output.
The loadStringTemplate method is a method that replaces the body part of the first argument by embedding the value passed to the third argument in the string passed to the second argument.
The return value is Promise. After the template is embedded in the web page , the newly embedded template can be binded with js, it will be resolved.
The array of top-level nodes in the loaded template is passed to resolve.
Let's take a look at the template method of index.js that creates the second argument of the loadStringTemplate method.
Returning just a template literal.
By attaching the attribute starting with data- to the tag, the third argument passed to loadStringTemplate can be embedded.
In the string passed to the second argument of the loadStringTemplate method, the third argument of the loadStringTemplate method can be used with the variable name v. This is the rule of this framework.
Therefore, <div data-text='v.key1'></div> will output the key1 element of the third argument of the loadStringTemplate method with HTML escape to the body part of this tag.
data-tag ='hidden' outputs only the body part of this tag, not the tag.
data-html outputs the given value without html escaping.
If you add data-load-only ='true' to the script tag, the inside of the script tag will be interpreted as JavaScript and executed there. This script tag will be removed.
You can use a local variable called l in the template. l is an object. This is the rule of this framework.
data-attr set the attribute value using setAttribute.
data-prop set the value in the DOM using the = operator. You can specify nested object.
data-if output the tag if the value is true.
data-elseif is executed if the previous data-if value is false, and output the tag if the given value is true.
data-else output the tag if the previous data-if and data-elseif values ​​are false.
Use data-for-start, data-for-end, data-for-step, and data-for-skip together. The data-for-start is evaluated first, and while data-for-end is true, the tag is repeatedly output. Data-for-step is evaluated every time the tag is output. If data-for-skip is true, iterative processing is not performed.
data-continue returns to the beginning of the loop. The value to be set specifies how many loops to return to. Specify 2 to return to the beginning of the top-level loop of the double loop.
The data-break breaks out of the loop. The value to be set specifies how many loops to return to. Specify 2 to return to the beginning of the top-level loop of the double loop.
Use data-foreach, data-foreach-key, data-foreach-value, data-foreach-skip, and data-foreach-end together. Iterates over the array or object specified in data-foreach. The string specified in data-foreach-key becomes the key of the local variable l, and the key of the array or object specified in data-foreach is stored there. The string specified in data-foreach-value becomes the key of the local variable l, and the element value of the array or object specified in data-foreach is stored there.If data-foreach-skip is true, iterative processing is not performed. If data-foreach-end is true, the iteration process ends.
Use data-while, data-while-skip, and data-while-step together. data-while output the tag repeatedly while the specified expression is true. If data-while-skip is true, iterative processing is not performed. data-while-step is executed during the second and subsequent iterations.
If there are attributes binded to js such as data-name, data-obj, data-list, they will be automatically binded by the framework.
If you use appendLoadStringTemplate instead of loadStringTemplate, the body part will be added to the body part instead of replacing it.
If you set beforeLoadStringTemplate instead of loadStringTemplate, the body part will be added just before the first argument instead of replacing.
If you set afterLoadStringTemplate instead of loadStringTemplate, the body part will be added immediately after the first argument instead of replacing.


Make the template a separate file

Let's change index.html and index.js to the following.

index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>
sample
</title>
<script id="fs-js" src="http://localhost:8000/js/fairysupport.min.js" data-page-root="http://localhost:8000/page"></script>
</head>
<body>
    <div data-obj="obj"></div>
    <div><button data-name="sample">sample</button></div>
</body>
</html>
index.js
export class Index {

    constructor() {
    }

    sample_click(event) {
        $f.loadTemplate(this.obj, 'tpl', {'key1': '<input type="text">', 'key2': {'val1': 2}, 'key3': {"key1": "str1", "key2": "str2", "key3": "str3", "key4": "str4", "key5": "str5"}})
        .then(this.success.bind(this))
        .catch(this.error.bind(this));
    }

    sample2_input(event) {
        this.obj2.textContent = event.target.value;
    }

    success(nodeList) {
        alert("success");
    }

    error(exception) {
        alert("error");
        console.error(exception);
    }

}

Let's create src/js/templates/tpl.html

tpl.html

<div>--data-text--</div>
<div data-text='v.key1'></div>
<div data-text='v.key1' data-tag='hidden'></div>

<div>--data-html--</div>
<div data-html='v.key1'></div>

<div>--script--</div>
<script data-load-only='true'>
    l.var = 1 + 2;
</script>
<div data-text='l.var'></div>

<div>--data-attr--</div>
<script data-load-only='true'>
    l.attr = {"style": "color: white; background-color: black;", "title" : "sample"};
</script>
<div data-attr='l.attr'>data-attr</div>
<div data-attr='{"style": "color: white; background-color: black;", "title" : "sample"}'>data-attr</div>

<div>--data-prop--</div>
<script data-load-only='true'>
    l.prop = {"style": {"color" : "white", "backgroundColor": "black"}, "title" : "sample"};
</script>
<div data-prop='l.prop'>data-prop</div>
<div data-prop='{"style": {"color" : "white", "backgroundColor": "black"}, "title" : "sample"}'>data-prop</div>

<div>--data-if--</div>
<div data-if='v.key2.val1 === 1'>
    v.key2.val1 === 1
</div>
<div data-elseif='v.key2.val1 === 2'>
    v.key2.val1 === 2
</div>
<div data-else=''>
    else
</div>

<div>--data-for--</div>
<div data-for-start='l.i = 0' data-for-end='l.i < 10' data-for-step='l.i++'>
    <span data-if='l.i === 3' data-continue='1' data-tag='hidden'></span>
    <span data-if='l.i === 6' data-break='1' data-tag='hidden'></span>
    <div data-text='l.i'></div>
</div>

<div>--data-foreach--</div>
<div data-foreach='v.key3' data-foreach-key='arrKey' data-foreach-value='arrVal'>
    <span data-if='l.arrVal === "str2"' data-continue='1' data-tag='hidden'></span>
    <span data-if='l.arrVal === "str4"' data-break='1' data-tag='hidden'></span>
    <span data-text='l.arrKey'></span>
    <span>:</span>
    <span data-text='l.arrVal'></span>
</div>

<div>--data-while--</div>
<script data-load-only='true'>
    l.whileCount = -1;
</script>
<div data-while='l.whileCount < 8'>
    <script data-load-only='true'>
        l.whileCount++;
    </script>
    <div data-if='l.whileCount === 3' data-continue='1' data-tag='hidden'></div>
    <div data-if='l.whileCount === 6' data-break='1' data-tag='hidden'></div>
    <div data-text='l.whileCount'></div>
</div>

<input data-name='sample2' type='text'>
<div data-obj='obj2'></div>

In loadStringTemplate, the template is passed directly as a string, but you can use loadTemplate to put the template in a separate file.
Templates are created under src/js/templates with the extension html. This is the rule of this framework.
Give the file name under src/js/templates to the second argument of loadTemplate.
You can also create subdirectories under src/js/templates. In that case, pass the string as the second argument of loadTemplate separated by periods.
For example, if you created src/js/templates/sub/tpl.html, pass 'sub.tpl' as the second argument of loadTemplate.
If you use appendLoadTemplate instead of loadTemplate, the body part will be added to the body part instead of replacing it.
If you set beforeLoadTemplate instead of loadTemplate, the body part will be added just before the first argument instead of replacing.
If you set afterLoadTemplate instead of loadTemplate, the body part will be added immediately after the first argument instead of replacing.


Template nesting

Example

<script data-load-only='true'>
        l.nestVal = {'key1': '<input type="text">', 'key2': {'val1': 2}, 'key3': {"key1": "str1", "key2": "str2", "key3": "str3", "key4": "str4", "key5": "str5"}};
</script>
<div data-template='tpl2' data-template-variable='l.nestVal'></div>

The data-template attribute value is the same as the second argument of loadTemplate.
The data-template-variable attribute value is the same as the third argument of loadTemplate.
The template is loaded inside the tag with the data-template and data-template-variable attributes.

Receive the variables to pass to the template from the server. Part 1

Until now, the value that can be used with the variable name v in the template was given by the json created in js, but this can be the json received from the server.
Let's create src/js/env/envValue.local.json and change index.js to the following.

src/js/env/envValue.local.json
{
    "apiRoot" : "http://localhost:8080"
}
index.js
export class Index {

    constructor() {
    }

    sample_click(event) {
        $f.resJsonTemplate(this.obj, 'tpl', $f.envValue('apiRoot') + '/tpl.php', {'sample_key': 'sample_value'})
        .then(this.success.bind(this))
        .catch(this.error.bind(this));
    }

    sample2_input(event) {
        this.obj2.textContent = event.target.value;
    }

    success(nodeList) {
        alert("success");
    }

    error(exception) {
        alert("error");
        console.error(exception);
    }

}

Let's create tpl.php and place it on a web server with CORS settings.
Please prepare your own web server with CORS settings.
Here, as an example, use the header method in PHP to set CORS. PHP server is http://localhost:8080.

tpl.php
<?php
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Origin: http://localhost:8000");
header("Access-Control-Allow-Headers: Accept, Content-Type, X-Requested-With");
header("Content-Type: application/json; charset=UTF-8");

$rawRequest = file_get_contents("php://input");
$jsonRequest = json_decode($rawRequest, true);

$responseJson = array(
    'key1' => '<input type="text">',
    'key2' => array(
        'val1' => 2
    ),
    'key3' => array(
        "key1" => "str1",
        "key2" => "str2",
        "key3" => "str3",
        "key4" => "str4",
        "key5" => "str5"
    ),
    'request_value' => $jsonRequest['sample_key']
);

echo json_encode($responseJson);

As an example, We have shown a server program that returns json using PHP. Suppose this is located directly under the document root.
Use resJsonTemplate instead of loadTemplate.
Pass the file name under src/js/templates to the second argument.
Pass the URL that returns json as the third argument.
Pass the request parameter to send to the URL that returns json in the 4th argument.
If you want to set withCredentials to true (if you want to send cookies), pass true to the 5th argument.
resJsonTemplate will POST the data given in the 4th argument to the URL given in the 3rd argument. Pass the JSON of that response to the template.
If you use appendResJsonTemplate instead of resJsonTemplate, the body part will be added to the body part instead of replacing it.
If you set beforeResJsonTemplate instead of resJsonTemplate, the body part will be added just before the first argument instead of replacing.
If you set afterResJsonTemplate instead of resJsonTemplate, the body part will be added immediately after the first argument instead of replacing.


Receive the variables to pass to the template from the server. Part 2

We sent the json to the server earlier, but we can also send the form.
Let's changeindex.js, index.html、tpl.php

index.js
export class Index {

    constructor() {
    }

    sample_click(event) {
        $f.resJsonTemplateByForm(this.obj, 'tpl', $f.envValue('apiRoot') + '/tpl.php', this.sampleForm)
        .then(this.success.bind(this))
        .catch(this.error.bind(this));
    }

    sample2_input(event) {
        this.obj2.textContent = event.target.value;
    }

    success(nodeList) {
        alert("success");
    }

    error(exception) {
        alert("error");
        console.error(exception);
    }

}
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>
sample
</title>
<script id="fs-js" src="http://localhost:8000/js/fairysupport.min.js" data-page-root="http://localhost:8000/page"></script>
</head>
<body>
    <div data-obj="obj"></div>
    <div><button data-name="sample">sample</button></div>
    <div>
        <form data-obj="sampleForm">
            <input name="sample_key" type="text" value="sample_value">
        </form>
    </div>
</body>
</html>
tpl.php
<?php
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Origin: http://localhost:8000");
header("Access-Control-Allow-Headers: Accept, Content-Type, X-Requested-With");
header("Content-Type: application/json; charset=UTF-8");

$responseJson = array(
    'key1' => '<input type="text">',
    'key2' => array(
        'val1' => 2
    ),
    'key3' => array(
        "key1" => "str1",
        "key2" => "str2",
        "key3" => "str3",
        "key4" => "str4",
        "key5" => "str5"
    ),
    'request_value' => $_REQUEST['sample_key']
);

echo json_encode($responseJson);

Added form tag to index.html and added data-obj="sampleForm".
index.js uses resJsonTemplateByForm instead of resJsonTemplate.
Pass a form object to send to the URL that returns json as the fourth argument.
If you want to set withCredentials to true (if you want to send cookies), pass true to the 5th argument.
resJsonTemplateByForm POST the form passed in the 4th argument to the URL passed in the 3rd argument. Pass the JSON of that response to the template.
If you use appendResJsonTemplateByForm instead of resJsonTemplateByForm, the body part will be added to the body part instead of replacing it.
If you set beforeResJsonTemplateByForm instead of resJsonTemplateByForm, the body part will be added just before the first argument instead of replacing.
If you set afterResJsonTemplateByForm instead of resJsonTemplateByForm, the body part will be added immediately after the first argument instead of replacing.


Receive the template from the server. Part 1

Get the template from an external server.
Let's changeindex.js, index.html

index.js
export class Index {

    constructor() {
    }

    sample_click(event) {
        $f.resHtmlTemplate(this.obj,
                           $f.envValue('apiRoot') + '/tpl2.php',
                           {'sample_key': 'sample_value'},
                           {'key1': '<input type="text">', 'key2': {'val1': 2}, 'key3': {"key1": "str1", "key2": "str2", "key3": "str3", "key4": "str4", "key5": "str5"}})
        .then(this.success.bind(this))
        .catch(this.error.bind(this));
    }

    sample2_input(event) {
        this.obj2.textContent = event.target.value;
    }

    success(nodeList) {
        alert("success");
    }

    error(exception) {
        alert("error");
        console.error(exception);
    }

}
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>
sample
</title>
<script id="fs-js" src="http://localhost:8000/js/fairysupport.min.js" data-page-root="http://localhost:8000/page"></script>
</head>
<body>
    <div data-obj="obj"></div>
    <div><button data-name="sample">sample</button></div>
</body>
</html>

Let's create tpl2.php and place it

tpl2.php
<?php
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Origin: http://localhost:8000");
header("Access-Control-Allow-Headers: Accept, Content-Type, X-Requested-With");
header("Content-Type: application/json; charset=UTF-8");

$rawRequest = file_get_contents("php://input");
$jsonRequest = json_decode($rawRequest, true);
?>
<div>--requestData--</div>
<div><?php echo htmlspecialchars($jsonRequest['sample_key'], ENT_QUOTES)?></div>

<div>--data-text--</div>
<div data-text='v.key1'></div>
<div data-text='v.key1' data-tag='hidden'></div>

<div>--data-html--</div>
<div data-html='v.key1'></div>

<div>--script--</div>
<script data-load-only='true'>
    l.var = 1 + 2;
</script>
<div data-text='l.var'></div>

<div>--data-attr--</div>
<script data-load-only='true'>
    l.attr = {"style": "color: white; background-color: black;", "title" : "sample"};
</script>
<div data-attr='l.attr'>data-attr</div>
<div data-attr='{"style": "color: white; background-color: black;", "title" : "sample"}'>data-attr</div>

<div>--data-prop--</div>
<script data-load-only='true'>
    l.prop = {"style": {"color" : "white", "backgroundColor": "black"}, "title" : "sample"};
</script>
<div data-prop='l.prop'>data-prop</div>
<div data-prop='{"style": {"color" : "white", "backgroundColor": "black"}, "title" : "sample"}'>data-prop</div>

<div>--data-if--</div>
<div data-if='v.key2.val1 === 1'>
    v.key2.val1 === 1
</div>
<div data-elseif='v.key2.val1 === 2'>
    v.key2.val1 === 2
</div>
<div data-else=''>
    else
</div>

<div>--data-for--</div>
<div data-for-start='l.i = 0' data-for-end='l.i < 10' data-for-step='l.i++'>
    <span data-if='l.i === 3' data-continue='1' data-tag='hidden'></span>
    <span data-if='l.i === 6' data-break='1' data-tag='hidden'></span>
    <div data-text='l.i'></div>
</div>

<div>--data-foreach--</div>
<div data-foreach='v.key3' data-foreach-key='arrKey' data-foreach-value='arrVal'>
    <span data-if='l.arrVal === "str2"' data-continue='1' data-tag='hidden'></span>
    <span data-if='l.arrVal === "str4"' data-break='1' data-tag='hidden'></span>
    <span data-text='l.arrKey'></span>
    <span>:</span>
    <span data-text='l.arrVal'></span>
</div>

<div>--data-while--</div>
<script data-load-only='true'>
    l.whileCount = -1;
</script>
<div data-while='l.whileCount < 8'>
    <script data-load-only='true'>
        l.whileCount++;
    </script>
    <div data-if='l.whileCount === 3' data-continue='1' data-tag='hidden'></div>
    <div data-if='l.whileCount === 6' data-break='1' data-tag='hidden'></div>
    <div data-text='l.whileCount'></div>
</div>

<input data-name='sample2' type='text'>
<div data-obj='obj2'></div>

Use resHtmlTemplate.
Pass the URL to return the template as the second argument.
In the third argument, pass the request parameter to be sent to the URL that returns the template..
Pass the object used by the variable name v in the template as the fourth argument.
If you want to set withCredentials to true (if you want to send cookies), give true to the 5th argument.
resHtmlTemplate POST the data passed in the third argument to the URL passed in the second argument. Use that response as a template.
If you use appendResHtmlTemplate instead of resHtmlTemplate, the body part will be added to the body part instead of replacing it.
If you set beforeResHtmlTemplate instead of resHtmlTemplate, the body part will be added just before the first argument instead of replacing.
If you use afterResHtmlTemplate instead of resHtmlTemplate, the body part will be added immediately after the first argument instead of replacing.


Receive the template from the server. Part 2

We sent the json to the server earlier, but we can also send the form.
Let's changeindex.js, index.html、tpl2.php

index.js
export class Index {

    constructor() {
    }

    sample_click(event) {

        $f.resHtmlTemplateByForm(this.obj,
                                 $f.envValue('apiRoot') + '/tpl2.php',
                                 this.sampleForm,
                                 {'key1': '<input type="text">', 'key2': {'val1': 2}, 'key3': {"key1": "str1", "key2": "str2", "key3": "str3", "key4": "str4", "key5": "str5"}})
        .then(this.success.bind(this))
        .catch(this.error.bind(this));
    }

    sample2_input(event) {
        this.obj2.textContent = event.target.value;
    }

    success(nodeList) {
        alert("success");
    }

    error(exception) {
        alert("error");
        console.error(exception);
    }

}
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>
sample
</title>
<script id="fs-js" src="http://localhost:8000/js/fairysupport.min.js" data-page-root="http://localhost:8000/page"></script>
</head>
<body>
    <div data-obj="obj"></div>
    <div><button data-name="sample">sample</button></div>
    <div>
        <form data-obj="sampleForm">
            <input name="sample_key" type="text" value="sample_value">
        </form>
    </div>
</body>
</html>
tpl2.php
<?php
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Origin: http://localhost:8000");
header("Access-Control-Allow-Headers: Accept, Content-Type, X-Requested-With");
header("Content-Type: application/json; charset=UTF-8");

?>
<div>--requestData--</div>
<div><?php echo htmlspecialchars($_REQUEST['sample_key'], ENT_QUOTES)?></div>


<div>--data-text--</div>
<div data-text='v.key1'></div>
<div data-text='v.key1' data-tag='hidden'></div>

<div>--data-html--</div>
<div data-html='v.key1'></div>

<div>--script--</div>
<script data-load-only='true'>
    l.var = 1 + 2;
</script>
<div data-text='l.var'></div>

<div>--data-attr--</div>
<script data-load-only='true'>
    l.attr = {"style": "color: white; background-color: black;", "title" : "sample"};
</script>
<div data-attr='l.attr'>data-attr</div>
<div data-attr='{"style": "color: white; background-color: black;", "title" : "sample"}'>data-attr</div>

<div>--data-prop--</div>
<script data-load-only='true'>
    l.prop = {"style": {"color" : "white", "backgroundColor": "black"}, "title" : "sample"};
</script>
<div data-prop='l.prop'>data-prop</div>
<div data-prop='{"style": {"color" : "white", "backgroundColor": "black"}, "title" : "sample"}'>data-prop</div>

<div>--data-if--</div>
<div data-if='v.key2.val1 === 1'>
    v.key2.val1 === 1
</div>
<div data-elseif='v.key2.val1 === 2'>
    v.key2.val1 === 2
</div>
<div data-else=''>
    else
</div>

<div>--data-for--</div>
<div data-for-start='l.i = 0' data-for-end='l.i < 10' data-for-step='l.i++'>
    <span data-if='l.i === 3' data-continue='1' data-tag='hidden'></span>
    <span data-if='l.i === 6' data-break='1' data-tag='hidden'></span>
    <div data-text='l.i'></div>
</div>

<div>--data-foreach--</div>
<div data-foreach='v.key3' data-foreach-key='arrKey' data-foreach-value='arrVal'>
    <span data-if='l.arrVal === "str2"' data-continue='1' data-tag='hidden'></span>
    <span data-if='l.arrVal === "str4"' data-break='1' data-tag='hidden'></span>
    <span data-text='l.arrKey'></span>
    <span>:</span>
    <span data-text='l.arrVal'></span>
</div>

<div>--data-while--</div>
<script data-load-only='true'>
    l.whileCount = -1;
</script>
<div data-while='l.whileCount < 8'>
    <script data-load-only='true'>
        l.whileCount++;
    </script>
    <div data-if='l.whileCount === 3' data-continue='1' data-tag='hidden'></div>
    <div data-if='l.whileCount === 6' data-break='1' data-tag='hidden'></div>
    <div data-text='l.whileCount'></div>
</div>

<input data-name='sample2' type='text'>
<div data-obj='obj2'></div>

Added form tag to index.html and added data-obj="sampleForm".
index.js uses resHtmlTemplateByForm instead of resHtmlTemplate.
Pass the form object to be sent to the URL that returns the template as the third argument.
Pass the object used by the variable name v in the template as the fourth argument.
If you want to set withCredentials to true (if you want to send cookies), pass true to the 5th argument.
resHtmlTemplateByForm POST the form passed in the third argument to the URL passed in the second argument. Use that response as a template.
If you use appendResHtmlTemplateByForm instead of resHtmlTemplateByForm, the body part will be added to the body part instead of replacing it.
If you set beforeResHtmlTemplateByForm instead of resHtmlTemplateByForm, the body part will be added just before the first argument instead of replacing.
If you set afterResHtmlTemplateByForm instead of resHtmlTemplateByForm, the body part will be added immediately after the first argument instead of replacing.


Use the DOM displayed on the screen as a template

Let's change index.js, index.html

index.js
export class Index {

    constructor() {
    }

    init() {
        $f.useDomAsTemplate(this.obj, {'key': {'val1': 2}})
        .then(this.success.bind(this))
        .catch(this.error.bind(this));
    }

    success(nodeList) {
        this.obj.style.display = "block";
    }

    error(exception) {
        alert("error");
        console.error(exception);
    }

}
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>
sample
</title>
<script id="fs-js" src="http://localhost:8000/js/fairysupport.min.js" data-page-root="http://localhost:8000/page"></script>
</head>
<body>
    <div data-obj="obj" style="display:none">
        <div data-if='v.key.val1 === 1'>
            v.key.val1 === 1
        </div>
        <div data-elseif='v.key.val1 === 2'>
            v.key.val1 === 2
        </div>
        <div data-else=''>
            else
        </div>
    </div>
</body>
</html>

Call useDomAsTemplate in index.js.
Treats the DOM passed to the first argument as a template.
Pass the object used by the variable name v in the template as the second argument.


Next page Single component event handling

table of contents