Email Tag
<et2-email-tag> | Et2EmailTag
Overview
Display a single email address On hover, queries the server to see if the email is associated with a contact already. If it is, we show the contact’s avatar, clicking it opens CRM view for that contact. If the email is unknown, we show and Add icon. Clicking it opens the add contact dialog with the email pre-filled.
Tag is usually used in a Et2EmailSelect with multiple=true, but there’s no reason it can’t go anywhere
Examples
A tag for one email address. It is what et2-email renders each address as - the recipients of a mail, the participants of an event - and what it adds over a plain tag is that it knows the difference between an address and a person.
Two things follow from that. It can show the address in whatever form is most readable, because
"Ralf Becker" <rb@example.org> carries a name that does not need to be shown alongside
the address. And on hover it asks the server whether that address belongs to a contact: if it does, the tag
shows the contact’s avatar and clicking it opens the contact; if it does not, it shows an add icon that
opens a new contact with the address already filled in.
The contact lookup is the half that needs a server, and this documentation site has none. The previews below render and format correctly, but the avatar / add-contact icon at the front of each tag stays a spinner permanently: the lookup is a single batched request, and when it fails nothing resolves the tag’s pending prefix, so the spinner has no timeout and no error state to fall back to. In an application the request answers and you get an avatar or an add icon instead.
Display format
emailDisplay decides what is shown. The address itself is unchanged - it is only the label that
gets shorter.
full-Ralf Becker <rb@example.org>name-Ralf Beckerdomain-Ralf Becker (example.org), the defaultemail-rb@example.org
domain is the default because it is the compromise that matters in mail: you see who it is, and
you can still tell rb@example.org from rb@example.com at a glance.
<et2-email-tag value="Ralf Becker <rb@example.org>" emailDisplay="full"></et2-email-tag>
<et2-email-tag value="Ralf Becker <rb@example.org>" emailDisplay="name"></et2-email-tag>
<et2-email-tag value="Ralf Becker <rb@example.org>" emailDisplay="domain"></et2-email-tag>
<et2-email-tag value="Ralf Becker <rb@example.org>" emailDisplay="email"></et2-email-tag>
When the address carries no name there is nothing to shorten to, so every format but full falls
back to the address.
<et2-email-tag value="rb@example.org" emailDisplay="name"></et2-email-tag>
The tag’s own default is domain, but a tag inside an
et2-email is handed the field’s format instead, and that one starts from
the user’s Email display preference
- so a user who wants to see full addresses sees them everywhere without any template saying so.
Hovering over a known contact
Nothing to set - it is what the widget does. The full address is always the tag’s title, so the
part that was shortened away is still one hover from being readable.
<et2-email-tag value="Ralf Becker <rb@example.org>"></et2-email-tag>
Without the contact integration
contactPlus is on by default and turns off the hover behaviour. It has to be set as a property,
not an attribute: it is a boolean that defaults to true, and a boolean attribute counts as set whatever its
value, so contactPlus="false" in a template switches it on.
this.et2.getWidgetById("tag").contactPlus = false;
Removable
As on any tag, removable adds the x and fires sl-remove rather than removing
anything itself. et2-email is what normally passes it in.
<et2-email-tag id="email-tag-remove" value="Ralf Becker <rb@example.org>" removable></et2-email-tag>
<script>
const emailTag = document.getElementById("email-tag-remove");
emailTag.addEventListener("sl-remove", () => {emailTag.remove();});
</script>
In an email field
What you would actually write:
<et2-email id="to" multiple label="To"></et2-email>
Properties
| Name | Description | Reflects | Type | Default |
|---|---|---|---|---|
emailDisplay
|
What to display for the selected email addresses - full: “Mr Test User test@example.com - name: “Mr Test User” - domain: “Mr Test User (example.com)” - email: “test@example.com” If name is unknown, we’ll use the email instead. |
"full" | "email" | "name" | "domain"
|
"domain"
|
|
_contactPlusNode
|
Get the node that is shown & clicked on to add email as contact |
HTMLElement
|
- |
Learn more about attributes and properties.
Inherited properties (22)
Et2Widget
| Name | Description |
|---|---|
accesskey |
Accesskey provides a hint for generating a keyboard shortcut for the current element. The attribute value must consist of a single printable character. |
actions |
Set Actions on the widget Each action is defined as an object: move: { type: “drop”, acceptedTypes: “mail”, icon: “move”, caption: “Move to” onExecute: javascript:mail_move” } This will turn the widget into a drop target for “mail” drag types. When “mail” drag types are dropped, the global function mail_move(egwAction action, egwActionObject sender) will be called. The ID of the dragged “mail” will be in sender.id, some information about the sender will be in sender.context. The etemplate2 widget involved can typically be found in action.parent.data.widget, so your handler can operate in the widget context easily. The location varies depending on your action though. It might be action.parent.parent.data.widget To customise how the actions are handled for a particular widget, override _link_actions(). It handles the more widget-specific parts. |
align |
Used by Et2Box to determine alignment. Allowed values are left, right |
class |
CSS Class. This class is applied to the outside, on the web component itself. Due to how WebComponents work, this might not change anything inside the component. |
data |
Set the dataset from a CSV |
deferredProperties |
Any attribute that refers to row content cannot be resolved immediately, but some like booleans cannot stay a string because it’s a boolean attribute. We store them for later, and parse when they’re fully in their row. If you are creating a widget that can go in a nextmatch row, and it has boolean attributes that can change for each row, add those attributes into deferredProperties |
disabled |
Defines whether this widget is visibly disabled. The widget is still visible, but clearly cannot be interacted with. Widgets disabled in the template will not return a value to the application code, even if re-enabled via javascript before submitting. To allow a disabled widget to be re-enabled and return a value, disable via javascript in the app’s et2_ready() instead of an attribute in the template file. |
dom_id |
Get the actual DOM ID, which has been prefixed to make sure it’s unique. |
hidden |
The widget is not visible. As far as the user is concerned, the widget does not exist. Widgets hidden with an attribute in the template may not be created in the DOM, and will not return a value. Widgets can be hidden after creation, and they may return a value if hidden this way. |
id |
Get the ID of the widget |
label |
The label of the widget This is usually displayed in some way. It’s also important for accessability. This is defined in the parent somewhere, and re-defining it causes labels to disappear |
noLang |
Disable any translations for the widget |
parentId |
Parent is different than what is specified in the template / hierarchy. Widget ID of another node to insert this node into instead of the normal location |
statustext |
Tooltip which is shown for this element on hover |
styles |
WebComponent * |
options |
Get property-values as object |
supportedWidgetClasses |
et2_widget compatability |
SlTag (Shoelace)
| Name | Description |
|---|---|
pill |
Draws a pill-style tag with rounded edges. |
removable |
Makes the tag removable and shows a remove button. |
size |
The tag’s size. |
variant |
The tag’s theme variant. |
LitElement
| Name | Description |
|---|---|
updateComplete |
A read-only promise that resolves when the component has finished updating. |
Inherited methods (21)
Et2Widget
| Name | Description |
|---|---|
checkCreateNamespace() |
Checks whether a namespace exists for this element in the content array. If yes, an own perspective of the content array is created. If not, the parent content manager is used. Constructor attributes are passed in case a child needs to make decisions |
clone() |
Creates a copy of this widget. |
createElementFromNode() |
Create a et2_widget from an XML node. First the type and attributes are read from the node. Then the readonly & modifications arrays are checked for changes specific to the loaded data. Then the appropriate constructor is called. After the constructor returns, the widget has a chance to further initialize itself from the XML node when the widget’s loadFromXML() method is called with the node. |
getArrayMgr() |
Returns the array manager object for the given part |
getArrayMgrs() |
Returns an associative array containing the top-most array managers. |
getChildren() |
Get child widgets Use |
getInstanceManager() |
Returns the instance manager |
getPath() |
Returns the path into the data array. By default, array manager takes care of this, but some extensions need to override this |
getRoot() |
Returns the base widget Usually this is the same as getInstanceManager().widgetContainer |
loadFromXML() |
Loads the widget tree from an XML node |
loadingFinished() |
Needed for legacy compatability. |
parseXMLAttrs() |
The parseXMLAttrs function takes an XML DOM attributes object and adds the given attributes to the _target associative array. This function also parses the legacyOptions. N.B. This is only used for legacy widgets. WebComponents use transformAttributes() and do their own handling of attributes. |
set_label() |
NOT the setter, since we cannot add to the DOM before connectedCallback() TODO: This is not best practice. Should just set property, DOM modification should be done in render https://lit-element.polymer-project.org/guide/templates#design-a-performant-template |
setArrayMgr() |
Sets the array manager for the given part |
setArrayMgrs() |
Sets all array manager objects - this function can be used to set the root array managers of the container object. |
setInstanceManager() |
Set the instance manager Normally this is not needed as it’s set on the top-level container, and we just return that reference |
_handleClick() |
Click handler calling custom handler set via onclick attribute to this.onclick |
destroy() |
et2_widget compatability |
set_class() |
Set the widget class |
set_disabled() |
Wrapper on this.disabled because legacy had it. |
set_statustext() |
supports legacy set_statustext |