This document (version 0.1) defines a hook service according to the terms set out in the core specification.
Under the hook service, a block can invite embedding application to take over the rendering of an element within the block (the hook), allowing embedding applications to provide users with application-specific views of specific data types without the block needing to know about them.
The service is designed to meet the following aims:
The service meets these aims by allowing blocks to delegate visualizing and editing functionality upwards to the embedding application.
The hook service is dependent on the graph service, as it relies on the existence of entities – use of the graph service is a prerequisite for use of the hook service.
Hook: an injection point blocks provide to embedding applications to allow them to optionally render or modify already rendered views associated with a property for an entity.
View: the elements the embedding application renders inside the hook (and associated functionality). A view may display read-only data or present editable data at the application’s discretion.
Blocks initiate hooks by asking embedding applications to take over a DOM node (the hook) and render the application’s preferred view of data of a specified type.
To request a view is rendered into a hook, a block MUST send a
hook message. The value for
hookId MUST be
null when a block first establishes a hook.
If the embedding application supports the requested hook type:
nodeor by attaching elements within it
pathon the entity associated with the specified
hookResponsemessage specifying a
hookIdto identify the hook with in future
If the embedding application does not support the requested hook type, it MUST respond with an error with a code of
If any of the required data is missing from the
hook message, the embedding application MUST respond with an error with a code of
Blocks may request that a hook is updated or removed.
On removal, embedding applications should cease any further activity in relation to the DOM node.
Updating is a convenience for blocks to change aspects of a hook without having to send a message to destroy a hook followed by a message to establish a hook with the new parameters.
Once a hook has been established, blocks MAY request their removal by sending a
hook message with the following values:
hookId: the id that was provided by the embedding application in the original
path: whatever values are currently applied to the hook
If an embedding application receives a
hook message with a value of
node, it MUST cease any activity and remove any subscriptions in relation to the
node (e.g. it should not make further modifications to the node, and should remove event listeners).
Once a hook has been established, blocks MAY vary its implementation by sending a
hook message with the
hookId provided in the original response, and the following values as desired:
typeto request that the type of view is changed
pathto request that the data used to populate the view is retrieved from and persisted to the
pathon the specified entity
entityIdto request that data from a new entity is used
nodeto request that the view is rendered at a different place in the DOM
hook message is sent with a
hookId corresponding to a previously-established hook, embedding applications MUST update the view for that hook according to the new parameters.
If such a message specifies a new
node, the embedding application MUST follow the process for removing hooks for the previous
node (e.g. cease modification of and remove subscriptions from that node).
Hooks provide a way for applications to render their preferred view of data from a specific property belonging to a specific entity.
Applications should still provide the relevant data to the block, and should ensure that its representation matches that specified in the block’s schema (which may be different to how the application is using it in the hook).
Embedding applications MUST use any value under the specified
path in the properties in the specified entity to initialise the view they render.
As per the graph specification, embedding applications MUST provide a valid value for the specified
path for any entity when sending data to the block. This may involve a different representation of the data than the application stores. For example, if an entity type specifies
type: "string" for a property, and the application has stored data on that property as complex rich text objects (owing to previous or current use of the hook service for that property, or for some reason), the application MUST translate those rich text objects into a simple string when sending the property to the block, in order for the data send to comply with the entity schema.
The type of a hook request indicates the type of data the block is requesting a view to be rendered for. The specification permits any string, but we expect particular use to be made of
text, and to a lesser extent
As an example, take
text. The data structure for formatted text may be bespoke to the embedding application, and impossible for the block to predictably parse or generate. The expected text editing experience may involve custom formatting controls, or special inline actions or commands. By using the hook service to inject its own rich text editing input, an embedding application can provide the desired experience and functionality.
type of a hook MUST be a string.
Embedding applications MUST render an appropriate view for the specified type, if they support it (e.g. a type of
text should be rendered as something that appears to the user as text, however the application chooses to present it).
There are only two messages in the hook service: the
hook request from the block, and the
hookResponse acknowledgement from the embedding application.
The messages available for exchange in the hook service are defined in the service's JSON definition and are also listed below for ease of reference.
|object | null||yes||The DOM node the embedding application will render a view into, or modifying an already rendered view. If null, the view should be destroyed.|
|yes||The type of view for the hook. Technically permits any string, although we anticipate 'text', and to a lesser extent 'image' and 'video' being common.|
|string||no||The entityId of the entity which owns the data the hook should be rendered using. i.e. the entity which has the hook data stored in its properties in the separately provided 'path'|
|string||yes||A path expressed as a JSON path to a property present in the entity's schema, where the value used in rendering this view should be retrieved from and persisted to (if updated)|
|string | null||yes||The ID of the hook as provided in the response when first sending a hook message. This should be null in the first 'hook' message for a given node, and use the value provided by the embedding application in 'hookResponse' on subsequent messages.|
|string||yes||The id of the hook, which the block can use in subsequent 'hook' messages to request that a given hook is updated.|
Anyone with an existing application who wants to embed semantically-rich, reusable blocks in their product can use the protocol. Improve your app’s utility and tap into a world of structured data with no extra effort, for free.