You have been redirected from an outdated version of the article. Below is the content available on this topic. To view the old article click here.

element

Deprecated

The element keyword is an alias for this

Note: This keyword is deprecated in favor of this and will be removed in future releases!

Search results for "element"

Execution Flow

When a flow is called, execution will begin at it’s starting element. In case of no entry point being set or no elements being contained, the flow will simply return a null result. Otherwise the Flow Engine will evaluate the starting element and then proceed with the evaluation of the element connected to the initial element as next element. This continues until there is no more next element available, an error has been thrown or the evaluated element is a Return element, in which case the result of the element’s evaluation will be returned. Although this sums up the general execution flow of a Flow, there are notable exceptions to this in the form of specialized elements. For example a Decision element will branch into two execution paths and choose one based on the connected conditional elements. Likewise, a Loop element will enter a different execution path for each element and finally proceeds with the original next element.

Aggregate

Name Description
Prev Accepts another element’s Next socket
Next Connects to another element’s Prev socket
CurrentData Accepts another element’s DataSource. Given data is made available as currentData within the scripting context.
Data Accepts another element’s DataSource. Given data is start value of the aggregation and used to set it’s initial value.
DataTarget Connects to another element’s DataSource socket. Contains the aggregated data of the element.
ExceptionHandler If connected to an ExceptionHandler, exceptions thrown in the scripting context will be handled by the referenced handler.
Script context used to aggregate the data. Return value will be written to the element’s data.

Template Elements

As defined in the DOM specification, Content Elements must not have child nodes. To be able to mix template expressions and node structures, Structr provides a block-version of Content Elements, the so-called Template Elements (Template icon). Similar to Content Elements, Template Elements support different content types and allow for template expressions. However, in contrast to Content Elements, Template Elements can have children.

Dynamic Content / Repeater

DOM elements that are connected to the database or trigger database actions are called “active elements”. In the page tree, they are marked with a special colorful icon. Structr provides a range of other active elements: Active input elements, dynamic output elements, action buttons and repeater elements. In the following we make use of other active elements.

Sidebar

The sidebar provides a tree view that displays all Flows and packages. The default “Flows” entry acts as a root element that groups all elements. Left-clicking a Flow element in the tree will load it’s content into the canvas view and set it as active. Right-clicking elements in the tree view provides a context-menu that allows access to various functions.
When the root element is right-clicked, it will provide the option to create a new Flow or package. For Flow elements the menu will provide the option to rename or delete the currently selected flow. Packages can be renamed and deleted as well as providing the option to add new child Flows or packages. Using drag-and-drop on the icon of Flows or packages, existing elements can be moved in the tree hierarchy.

Connecting flow elements

Now that our Action contains a script, we want it to return its result. For this to happen we have to make sure the flow execution does not stop at the Action element. Drag a connection from the “Next” socket of the Action element to the “Prev” socket of the Return element to create an execution flow, indicated by the green color of the connection. Our function is now capable of returning something after the Action has been dealt with, but at this point in time, it will return an empty result, because we have not yet connected data to the Return element. In the same way the first connection was handled, create a connection between the elements “DataTarget” and “DataSource” sockets to create a data flow. When a node is being evaluated by the engine, it will try to consider connected data flows and make them available within its scripting context in the example of an Action or Return element.

Data Binding

The Page Rendering Engine allows developers to create dynamic markup elements by binding a scripting expression or database query to an element in the markup tree. A dynamic markup element is called a repeater. It is rendered to the output stream once for each object in the query or function result collection and will be displayed including its substructure. The current element can be accessed through a keyword, the so-called data key. The data key is valid in the entire subtree within the repeater element and can also be referenced in content nodes, templates or element attributes.

Templates

We start by introducing the template element. In Structr, templates are special elements that may be inserted into a page’s DOM tree at any position. Much like a content element, a template element has a body which is rendered into the page. However, in contrast to the content element, a template element may have children in the DOM tree, which will become important later on.

Filter

Name Description
Prev Accepts another element’s Next socket
Next Connects to another element’s Prev socket
DataSource Accepts another element’s DataTarget
DataTarget Connects to another element’s DataSource
Condition Acceps connections from logic elements and uses connected logic to determine whether an element of the given collection gets filtered

Data Flow and Handling

Whenever a Flow Element has a data source socket available, data can be made available to the element. If such an element has a connected data source, it will query data from it’s source before performing it’s own function. The data source itself can also potentially have another data source, which enables data to be recursively constructed from multiple data elements. In case of elements that allow scripting, the acquired data will be made available under the static data key. While this is true for all basic elements, Aggregate is a special case, because it takes two data source inputs and makes them available as data and currentData based on their respective socket.

Example Implementation

<div id="qrimage-wrapper">
<img id="qrimage" style="margin-left: calc(50% - 100px);">
<div>To use two factor authentication, scan this QR code with an authenticator app on your smartphone.</div>

<div class="text-sm mt-6">
<div>
<b>Android: </b>
<a class="cursor-pointer hover:text-blue-400 text-blue-700" href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en&gl=US">Google Authenticator</a> on Google Playstore
</div>
<div>
<b>Apple iOS: </b>
<a class="cursor-pointer hover:text-blue-400 text-blue-700" href="https://apps.apple.com/us/app/google-authenticator/id388497605">Google Authenticator</a> on App Store
</div>
</div>
</div>

<form action="#" id="twoFactorForm">
<input id="twoFactorToken" type="hidden" value="${request.token}">
<div class="my-6">
<label class="block text-sm font-medium leading-5 text-gray-700">Two Factor Code</label>
<input id="twoFactorCode" class="appearance-none block w-full px-3 py-2 bg-blue-100 border border-gray-300 rounded-md placeholder-gray-400 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 transition duration-150 ease-in-out sm:text-sm sm:leading-5">
</div>
<button type="submit" id="login-button" class="w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-500 focus:outline-none focus:border-blue-700 focus:shadow-outline-indigo active:bg-blue-700 transition duration-150 ease-in-out">Login</button>
</form>

<script>
document.addEventListener('DOMContentLoaded', () => {

// get all required elements
const qrimageWrapper = document.getElementById('qrimage-wrapper');
const token = document.getElementById('twoFactorToken').value;
const codeInput = document.getElementById('twoFactorCode').value;
const loginButton = document.getElementById('login-button');

let qrdata = (new URLSearchParams(location.search)).get('qrdata');

if (!qrdata) {
// remove qr code placeholder if user is not shown qr code
qrimageWrapper.remove();
} else {
// transform url-safe qr code to regular base64 to display as image
qrimageWrapper.querySelector('#qrimage').src = 'data:image/png;base64, ' + qrdata.replaceAll('_', '/').replaceAll('-', '+');
}

document.getElementById('twoFactorForm').addEventListener('submit', async (event) => {

event.preventDefault();

loginButton.disabled = true;

const response = await fetch('/structr/rest/login', {
method: 'POST',
body: JSON.stringify({
twoFactorToken: token,
twoFactorCode: codeInput
})
});

if (response.ok) {

loginButton.textContent = 'Login successful';
window.location.href = '/';

} else {

let buttonText = 'Login failed - is device time correct?';

let reason = response.headers.get('reason');

if (reason === 'wrongTwoFactorCode') {
buttonText = 'Two Factor Code is not correct';
}

loginButton.disabled = false;
loginButton.textContent = buttonText;

window.setTimeout(function() {
loginButton.textContent = 'Login';
loginButton.disabled = false;
}, 2000);
}
});
});
</script>

Rendering Engine

The HTML5 standard defines different types of elements: the so-called “block elements”, e.g. <div>, <p> or <table> that form the structure of a document, and “inline” elements like <a> and <span>, etc. The content of an element can be other elements, or so-called #text nodes as defined in the DOM specification.

ExceptionHandler

Exception handling within Flows can be realized using the ExceptionHandler element. If a Flow contains such element and the element is not connected via a red exception handling relationship, it will act as a global exception handler for all uncaught exceptions thrown within the flow. If an ExceptionHandler is connected to a supported element via a red connecting, it will act as handler for exceptions thrown by related elements.

Loop

Name Description
Prev Accepts another element’s Next socket
Next Connects to another element’s Prev socket
DataSource Accepts another element’s DataSource. Represents the collection to iterate.
DataTarget Accepts another element’s DataSource. Contains the object of the current iteration.
FirstAction Connects to another element’s Prev socket. Represents the first node to be called for each iteration of the collection.

Dynamic Content / Repeater

A repeater element is a DOM node that is made dynamic by binding a special template expression to it. In particular, we may bind a database query that produces a collection of all elements of type Project to a <row> element. When a repeater element is rendered into the page, the template expression is evaluated and the dom node is rendered into the page for each element in the result.

Note that the icon of the element in the page tree changed to indicate that it’s now an active element. Also note that in the preview output, there are multiple rows while there’s only a single <tr> in the DOM tree. This is because we turned the <tr> element into a so-called repeater element, i.e. it is repeated for each element of the result collection.

Call

Name Description
Prev Accepts another element’s Next socket
Next Connects to another element’s Prev socket
Parameters Accepts multiple ParameterInput element connections
DataTarget Connects to another element’s DataSource
Flow Allows the selection of a Flow to call with this element

Template Elements

Therefore, the rendering flow stops at template elements and does not render the remaining branch of the DOM tree. Instead, the template element has to explicitly invoke the rendering process for it’s child elements in the appropriate place. To accomplish this, Structr provides the children keyword and the render() function, as shown in the example below. While this makes the configuration of template elements a bit more subtle than that of content elements, it provides much more flexibility.

Icons

Icon Element type
Page icon Page
Brick icon Block element
Colored Bricks icon Repeater
Yellow Brick icon Shared Component
White Page icon Content element
Template icon Template
Shared Template icon Shared Template