request
The request helper block in the template is used as a declarative point for dynamically updating content based on requests to the server, and getting HTML from there.
Property | Type | Default | Description | Required |
---|---|---|---|---|
src | string | — | The source URL of the request | Yes |
method | string | ”GET” | The HTTP method used for the request | No |
after | string | — | Event trigger specification | No |
repeat | boolean | true | Whether the request repeats on subsequent triggers | No |
interval | number | — | Optional interval for repeated requests (in ms) | No |
indicators | HMPLIndicator[] | [] | Status-specific UI indicators | No |
autoBody | boolean | HMPLAutoBodyOptions | false | Configures automatic body generation | No |
memo | boolean | false | Enables response caching | No |
initId | string | number | — | Identifier for request initialization | No |
allowedContentTypes | HMPLContentTypes | [“text/html”] | Permitted response Content-Types | No |
disallowedTags | HMPLDisallowedTags | [] | HTML elements to remove from responses | No |
sanitize | HMPLSanitize | false | Enables HTML sanitization | No |
{{#request src="/api/test" method="get" after="click:.target" repeat=true interval=1000 indicators=[ { trigger: "pending", content: "<p>Loading...</p>" }, { trigger: "rejected", content: "<p>Error</p><button>reload</button>" } ] autoBody={ formData: true } memo=true initId="id1" allowedContentTypes=["text/html"] disallowedTags=["script", "style", "iframe"] sanitize=false}}{{/request}}
Nesting
Section titled “Nesting”Only indicator block helper.
{{#request src="/api/test"}} {{#indicator trigger="pending"}} <span>Loading...</span> {{/indicator}} {{#indicator trigger="error"}} <span>Error</span> {{/indicator}}{{/request}}
The src property specifies the target URL for the request.
{{#request src="/api/test"}}{{/request}}
method
Section titled “method”The method property specifies the HTTP method to be used for the request.
{{#request src="/api/test" method="POST"}}{{/request}}
The supported methods are GET
, POST
, PUT
, PATCH
, DELETE
, OPTIONS
, TRACE
.
The after property defines when to send the request, using the format ${event}:${selectors}
. Here, event
is the trigger (e.g., click
), and selectors
specify the target elements.
<div> <button id="btn">Click!</button> <div> Clicks: {{#request src="/api/clicks" after="click:#btn"}}{{/request}} </div></div>
In this example, no request is made to the server until the button
is pressed. For such cases, it is better to add another helper block that will be triggered during rendering.
repeat
Section titled “repeat”The repeat property controls whether a request re-executes on subsequent trigger events.
<div> <button id="btn">Click!</button> <div> {{#request src="/api/test" after="click:#btn" repeat=false}}{{/request}} </div></div>
In the example, we have repeat set to false
, which makes repeated requests to the server by clicking on the button
impossible.
interval
Section titled “interval”The interval property specifies the time in milliseconds between consecutive requests to the server, following the JavaScript setInterval
timing model.
The interval clearing function is available in the request context.
const templateFn = compile(`<div> <button id="btn">Start timer!</button> <div> Seconds: {{#request src="/api/timer" after="click:#btn" interval=1000 repeat=false }}{{/request}} </div></div>`);
const el = templateFn({ get: (prop, value, context) => { const { clearInterval } = context.request; switch (prop) { case "response": if (value?.outerHTML === `<span>10</span>`) { clearInterval(); } break; } }});
In this example we stop the timer when it reaches 10 seconds.
indicators
Section titled “indicators”The indicators property is intended to define the HTML content that should be rendered in response to a particular request status. This property enables authors to provide user interface feedback corresponding to specific states of a request initiated by the HMPL module.
The value is an array of each HMPLIndicator object.
<div> <button id="btn">Get HTML!</button> {{#request src="/api/getHTML" after="click:#btn" indicators=[ { trigger: "pending", content: "<p>Loading...</p>" }, { trigger: "403", content: "<p>Access error!</p>" } ] }}{{/request}}</div>
indicator
Section titled “indicator”An object describing what specific request status the HTML will be displayed on.
Property | Type | Description | Required |
---|---|---|---|
trigger | HMPLIndicatorTrigger | The status that the indicator is showing | Yes |
content | string | The HTML that is shown when the indicator is active | Yes |
{{#request src="/api/getHTML" indicators= [ { trigger: "pending", content: "<p>Loading...</p>" } ]}}{{/request}}
trigger
Section titled “trigger”The trigger property specifies the status condition under which the associated content should be displayed.
{ trigger: 403;}
The permissible values for trigger are:
- HTTP status codes within the range
400
to599
, indicating client and server errors as defined by the HTTP specification. - The string literal
"pending"
, representing the Promise state where a request is in progress and awaiting resolution. - The string literal
"rejected"
, representing a Promise rejection or a failed fetch operation. - The string literal
"error"
, a generic value that serves as a catch-all trigger, activated under either of the following circumstances:- A HTTP response with a status code between
400
and599
. - A
"rejected"
Promise
state.
- A HTTP response with a status code between
content
Section titled “content”The content property must be a plain string containing static HTML markup. This markup is not interpreted or extended by the HMPL module, and therefore does not support HMPL-specific syntax or dynamic bindings.
{ content: "<p>Loading...</p><div>Loading...</div>";}
Additionally, the value must be a single-line string — line breaks (e.g., \n
) or other control characters are not allowed.
autoBody
Section titled “autoBody”The autoBody property specifies automatic generation of the body
property within a RequestInit object.
The property accepts either a Boolean value or an HMPLAutoBodyOptions object, determining how the request body should be constructed.
<div> <form onsubmit=" function prevent(e){ e.preventDefault(); }; return prevent(event); " id="form"> <div class="form-example"> <label for="name">Enter example login:</label> <input type="text" name="login" id="login" required /> </div> <div class="form-example"> <input type="submit" value="Submit!" /> </div> </form> {{#request src="/api/login" after="submit:#form" autoBody=true indicators=[ { trigger: "pending", content: "<p>Loading...</p>" } ] }}{{/request}}</div>
It is important to note that automatic generation will only overwrite the existing body property if the HMPLRequestInit object is not derived from a RequestInit function. In such cases, the manually specified body value takes precedence.
If the value of autoBody is true, the module automatically generates a FormData
instance using the associated SubmitEvent target element and its submitter.
{ body: new FormData(event.target, event.submitter);}
AutoBody options
Section titled “AutoBody options”Settings object for each automatic generation
Property | Type | Description | Required |
---|---|---|---|
formData | boolean | Automatic body generation for form tag | No |
{ autoBody: { formData: true; }}
The memo property enables response caching for identical requests. When enabled:
- Identical requests return cached responses
- Only active when repeat is true
- Improves performance for repeated requests
<div> <button id="btn">Get the square root of 256!</button> <div> {{#request src="/api/getSquareRoot" after="click:#btn" memo=true}}{{/request}} </div></div>
The memoization process can be conceptually compared to disabling the no-cache
directive in the RequestCache API, as it prevents repeated fetching of the same resource within the same runtime environment.
That is, caching means that the DOM tree will not be redrawn if the response from the server is the same.
initId
Section titled “initId”The initId property establishes an explicit association between a request and a predefined initialization object. It references the id property of a corresponding entry in the RequestInit dictionary collection, determining the initialization parameters for the request.
const templateFn = compile(`<div> <button id="btn">Take a component with an API!</button> {{#request src="/api/getComponent" after="click:#btn" initId=1 indicators=[ { trigger: "pending", content: "<p>Loading...</p>" }, { trigger: "403", content: "<p>Access error!</p>" } ] }}{{/request}}</div>`);
templateFn([ { id: 1, value: { credentials: "omit" } }]);
const templateFn = compile(`<div> <button id="btn">Take a component with an API!</button> {{#request src="/api/getComponent" after="click:#btn" indicators=[ { trigger: "pending", content: "<p>Loading...</p>" }, { trigger: "403", content: "<p>Access error!</p>" } ] }}{{/request}}</div>`);
templateFn([ { id: 1, value: { credentials: "omit" } }]);
In this example, initId, if specified, passes RequestInit with credentials
with the value "omit"
, which does not pass credentials
to the server, thus access to the API will be limited. If we do not pass initId, then RequestInit will be empty, respectively, all its values will be default for fetch
.
allowedContentTypes
Section titled “allowedContentTypes”The allowedContentTypes property defines the list of permissible Content-Type
values within the headers of HTTP responses returned from server requests. This property enables content validation and type safety when processing server responses.
The property value may be either:
- The string literal
"\*"
, indicating that all content types compatible with the text method are allowed. - An array of string values, each representing an explicitly permitted
Content-Type
.
If the array is empty, behavior is equivalent to using "\*"
— all types supporting the text method are permitted.
{{#request src="/api/test" allowedContentTypes=[ "application/json; charset=utf-8" "text/plain" ]}}{{/request}}
For additional guidance on server-side configuration and content type handling, refer to the Server Configuration documentation.
disallowedTags
Section titled “disallowedTags”The disallowedTags property specifies HTML elements to remove from responses.
my-component.html
<script></script><div>My component</div><iframe></iframe><style></style>
index.hmpl
{{#request src="/api/get-my-component" disallowedTags=["script", "iframe", "style"]}}{{/request}}
<div>My component</div>
The supported methods are script
, iframe
, style
.
sanitize
Section titled “sanitize”The sanitize property enables DOMPurify-based HTML sanitization.
my-component.html
<script></script><div>My component</div>
index.hmpl
{{#request src="/api/get-my-component" sanitize=true}}{{/request}}
<div>My component</div>
Unlike disallowedTags, this is a more serious protection when working with uncontrolled API routes. The function that is used looks like this:
const newResponse = DOMPurify.sanitize(response);