Previous sections have given a shallow introduction to the underlying building blocks with an emphasis on how to use them to access predefined Message Type Model classes without fully understanding what they are nor how they work.
Future sections will look at how to build your own Message Type Model classes, as a first step to building your own custom Messaging Experiences.
To talk about how to build Custom Messages, one must first understand how the Message Types work. Messsage Type Views are built from the following Components:
|Message Viewer||A UI Component that accepts a Message as input and from it, instantiates a Message Type Model and a Message Type View|
|Message Type Model||Represents a specific type of Message such as an Image Message, exposing properties, methods and operations for interacting with that type of message|
|Message Type View||A rendering for a specific type of Message Type Model|
|Message View Container||A container that lays out the Message Type View with respect to other relevant information or widgets related to the Message|
The Message Type Model
A UI agnostic representation of a Message and all of its Message Parts that abstracts away the details of the Message and Parts. Instead of focusing on the message and its parts, it allows you to interact with properties and methods related to the nature of the data rather than the transport used to send the data.
- Text Message Model
- Image Message Model
- Carousel Message Model
- Location Message Model
Developers building their own Custom Messages would provide models such as:
- Calendar Message Model
- Submit Ticket Message Model
- Credit Card Form Message Model
Each Message Type Model represents a single Message Part, and zero or more child parts that add clarifying details to the Message Part. Each of those child Message Part objects may themselves be represented by a Message Type Model (described in these docs as a sub-model). Each sub-model typically has its own Message Part from which it receives its initial data. Conceptually there are two types of Message Part objects:
- The Root Part: This is a Message Part with a JSON
bodycontaining metadata describing the Model. In many cases, this metadata contains everything needed to describe the Model.
- The Child Parts: Each Message Part that is a Child Part has been associated with the parent Message Part using
parent-node-idvalues that establish who the parent node of this Message Part is and what role this object plays for that parent Message Part. These child Message Part objects might each represent an additional Message Type Model (as is done with the Carousel Model), or may refer to raw data parts (such as a Message Part containing a File for the File Model).
Because a Message Type Model can contain other Message Type Model objects, a sophisticated Message will be represented by a tree of Models that is initialized when the Root Model is created. Note that initialization will typically create every submodel of the tree as it does not know what submodels any given View may need. This could evolve to generating submodel on demand in the future.
Each Message contains a set of Message Part objects which are formed into a Tree by the XDK. The tree is formed by finding
each Message Part object’s MIME Type Attribute value
parent-node-id and finding another Message Part whose UUID portion of their
id property matches that
parent-node-id. This tree represents which Message Parts depend upon which other Message Parts.
From this tree of Message Part objects, a tree of Message Type Model is generated. Why is it a tree? A Carousel Model contains a collection of items that you can swipe through. Those items are each represented by their own Message Type Model. One of those models might be a Button Message Type Model that in turn contains a Product Message Type Model to which it is adding its buttons. The Product Message Model may have various Product Options beneith it in the tree.
- All model properties are expected to be camel cased (i.e.
- All model properties are transformed to snake case (i.e.
this_is_a_property) when being sent to the server
- Subproperties of a model’s properties that are not explicitly handled by the class will be sent as is without any transformation. Example:
customData.my_mixedCase_propertywill be sent to the server as
- MessageTypeModel_addModel(): Add a submodel to this Model
- MessageTypeModelgenerateMessage(): Generate a Message representing this Model
- MessageTypeModelsend(): Generate and send a Message representing this Model (calls MessageTypeModelgenerateMessage())
- MessageTypeModel_parseMessage(): Instantiate this Model from a Message’s data
- MessageTypeModelgetOneLineSummary(): Get a one line summary of the Model’s data for use within the Conversation List
- MessageTypeModelgetParentModel(): Lookup the Parent Model for which this Model is a Sub Model.
- MessageTypeModelgetParticipantResponse(): Get the Response to this Model from the specified User (Message Response based updates)
- Takes a single input: one Message Type Model
- Renders the core data represented by the model; this could be:
<layer-image-message-view />: Renders the Picture of an Image Model, and nothing else
<layer-file-message-view />: Renders a representation of the File from a File Model, and nothing else
<layer-receipt-message-view />: Renders details of a Receipt for an Receipt Model, which is actually almost the entire Receipt Message
- Selects an optional Message View Container that can render additional information from the Message Type Model
|Standard Message View Container||Adds a title, description and footer underneath a simple message; depends upon the Message Type Model providing a title, description and footer|
|Titled Message View Container||Adds a titlebar over the Message|
Why not just make titles or other resusable subcomponents a part of each Message Type View? Lets take the Image Message View as an example. The Image Message View should only know and care about how to render an Image. It does not care about the thousand different variations on how it can be laid out with additional information like titles, descriptions, etc, nor should it need to manage anything other than correctly rendering that image.
- If you put an Image Message into a Standard Message View Container, title, description and footer appear below the image
- If you put an Image Message into a List Message View Container (does not yet exist), title and description appear to the right of the image
- If you put an Image Message into a Titled Message View Container, a title goes over the image
Layout, contents, placement of elements is managed by the Message View Container, not the Image Message View. The Image Message View may state a preference for a certain type of Message View Container. Such preferences may be overridden by a Parent Message Type View (such as a Carousel, List, etc…).
The Standard Message View Container is used by most of the basic Message Type View components that the XDK ships with. It puts the Message Type View at the top, and has a bottom section that renders a Title, Description and Footer taken from the Message Type Model. Any Message Type Model that wants to be used with the Standard Message View Container should support:
Note that while the Image Message View and File Message View may use the Standard Message Type Container, there are Message Types such as the Receipt Message that would presumably never be used within this Container.
The Titled Message View Container adds a standard reusable title bar to Message Type View. Layer’s Receipt Message View and Choice Message View use this to add a title bar. Why not just build a title bar directly into the Message Type View ?
- This is a standard piece of functionality that many future messages will use
- Buttons, menus, actions, etc… may eventually be built into this titlebar which can be shared with other Message Type View classes
The Titled Message View Container currently supports the following methods:
- ChoiceMessageView_getIconClass() returns a CSS class that will let your app place an appropriate icon in the titlebar
- ChoiceMessageView_getTitle() returns a string to place in the title of the titlebar.
Both of these calls are made to the Message Type View, not the Message Type Model. The Model should know nothing of CSS classes that are used to load icons. The Model may or may not have a
title property, but a design for a Message Type View may have a title that is part of that design. Its up to the Message Type View to decide whether to handle these calls or to query the model for its answer.
The Message Viewer can be used with a
size='large' property or attribute.
var viewer = document.createElement('layer-message-viewer'); viewer.size = 'large'; viewer.model = myModel;
Doing so will cause the Large Viewer to be loaded if one is defined. A large message viewer is defined by setting the Message Model’s static
largeMessageRenderer as follows:
MyModelClass.largeMessageRenderer = 'layer-mytype-message-large-view';
With this setup,
<layer-mytype-message-large-view model=myModel /> will be rendered within the Message Viewer.
Typically a Message that supports this large view will have the
action (i.e. the action performed when a user taps/clicks) set to
layer-show-large-message. For example:
MyModelClass.defaultAction = 'layer-show-large-message';`
Clicking/tapping such a message will trigger the
layer-show-large-message and cause a
<layer-dialog /> to appear showing that message in its large form.
Large Message Views can be displayed anywhere, even outside of the
<layer-dialog />; however, this is not as well tested as showing these within the Dialog.
Note that only Audio and Video messages have defined Large Message Views at this time.Introduction Custom Message Types