Feature: #77268 - Introduce JavaScript trigger request API¶
See forge#77268
Description¶
JavaScript event handling the backend of the TYPO3 core is based on the optimistic assumption, that most executions can be executed sequentially and are processed just in time. This concept does not consider the fact that other nested components can defer the execution based on additional user input e.g. as used in confirmation dialogs.
That's why a trigger request API is introduced to first inform dependent components about a planned action which will defer the regular execution based on specific application state logic of registered components. In the current implementation, FormEngine's edit forms register themselves to be notified, thus accidentally closing modified forms by clicking e.g. the module menu any other page in the page tree can be handled.
Registering component¶
The following code attaches or detaches a particular component (a consumer) to be notified.
// FormEngine must implement the Consumable interface,
// thus having a function named consume(interactionRequest)
top.TYPO3.Backend.consumerScope.attach(FormEngine);
top.TYPO3.Backend.consumerScope.detach(FormEngine);
Invoking consumers¶
Registered consumers are invoked with a specific interaction request that has a defined action type and optionally additional information about the parent call (e.g. some client event issued by users). Invocations return a jQuery.Deferred() object that resolves when no consumers are registered or every consumer sends a resolve command as well - if only one consumer rejects, the collective invocation promise is rejected as well.
var deferred = TYPO3.Backend.consumerScope.invoke(
new TriggerRequest('typo3.setUrl', interactionRequest)
);
deferred
.then(function() { console.log('consumers are resolved'); })
.fail(function() { console.log('some consumer was rejected'); });
Creating interaction requests¶
Currently there are two types of requests, Client
that is based on some
client event (e.g. click
event) and Trigger
which may be based on some
parent request of type Interaction
- this is used to cascade actions.
var clickRequest = new ClientRequest('typo3.showModule', event);
var triggerRequestA = new TriggerRequest('typo3.a', clickRequest);
var triggerRequestB = new TriggerRequest('typo3.b', triggerRequestA);
In the example trigger
has all information from the initial click
event down to the specific typo3.
action type. The first request can be
resolved from the most specific request by trigger
and will return click
in this case.
Working with interaction requests¶
trigger
checks whetherRequest B. concerns (click Request) click
is an ancestor request in the cascade ofRequest trigger
(which is true, based on the previous example)Request B trigger
checks whetherRequest B. concerns Type ('typo3. show Module') typo3.
is the type of some ancestor request in the cascade ofshow Module trigger
(which is true, based on the previous example)Request B trigger
sets the property evaluated byRequest B. outer Most Request. set Processed Data ( {response: true}) click
toRequest. is Processed () true
and stores any custom user response (e.g. from some confirmation dialog) at the outer-most interaction request
Impact¶
Using interaction requests requires some modifications in the JavaScript processing
logic which changes from sequential processing to possibly deferred asynchronous
processing. This is required since e.g. user input is required first to be able
to continue the processing. The created promises are based on j
.