27
loading...
This website collects cookies to deliver better user experience
CountComponent
. This will extend HTMLElement (the browser's base type for all its elements):change tracking
. For the sake of this demo, we will return an array of a single string – the attribute name count
:getter
for the custom “count” attribute, and in the function, the attribute value count
is loaded with a call to getAttribute
, defaulting to the string "0"
. Once the data is loaded, we’re parsing it from JSON – we do this because any data that we store must be a string.super
to trigger the base logic for the HTML Element class. Add any other logic, or miss out calling super and you’ll see an error in your console and the element won’t work.connectedCallback
function. Implementing this callback will cause the code to run when the component is added to the DOM – it is similar to React's componentDidMount
function. In connectedCallback, we’re setting a default for the counter, and calling a function we’ll look at shortly called setContent
:disconnectedCallback
(shown here only for illustration purposes as we’re not running any code). The code in this function executes when your element is removed from the DOM and destroyed.attributeChangedCallback
. We will use this function to execute code whenever an observedAttribute
changes:setContent
is a function that the component calls when the component is added to the DOM, and when an update happens. The click handler in the above code can access the attributes of the element using the this
keyword, so on each click, we increment the value, in turn triggering a re-render.this.connectToAblyChannel
(which we’ll examine shortly):this.subscribedChannels
(which we will create in a connect
function) and unsubscribes from any Ably channels that have been used:connectToAblyChannel
function is where a lot of the real work happens. We start off by loading some configuration – we will set up a convention that we expect users to supply either their Ably API key, or a callback URL to an API that responds with an Ably token authentication request. To supply these values, and because we’re creating HTML elements, we expect them to be set as attributes on the element when it’s created in the markup.this
object.data-api-key
and data-get-token-url
. If an API key is found, it takes precedence, otherwise, we create an Ably JavaScript SDK configuration object that contains an “authUrl” property. Now that we have a configuration object (either an API key or a URL), we can create an instance of the Ably Realtime JavaScript SDK. It is important to point out that this Custom Element relies on the containing page having already included the Ably JavaScript SDK using a script element before it is executed. The following code comes after the configuration, inside the connectToAblyChannel
function:this.ably
, we will also create an empty array called subscribedChannels
.publish
function and a subscribe
function.ably.channels.get(channelName)
to get a channel. For this chat example, we want to let the AblyChatComponent decide which channels it will publish and subscribe on, effectively extending the API surface area of the Ably SDK (the set of things the API can do).args
:.apply
on the publish or subscribe calls from the Ably SDK to pass the rest of the variables to the SDK to publish or subscribe to messages.channelName
, to get the correct channel and keep track of it so we can unsubscribe when we unmount from the DOM. The following code will go inside the publish
function, below the arguments assignment. The subscribe function works similarlypublish
and subscribe
are virtually identical functions – with the exception that we’re passing to them the call to channel.publish
or channel.subscribe
, respectively.publish
or subscribe
with an extra channelName
parameter at the start of the call, and not worry about connecting or disconnecting from Ably channels.type="module"
as an attribute. When using ES6 modules, we can use import
in browser components, so to start here, we’re importing our AblyBaseComponent in order to extend it.constructor
, which in turn calls the constructor of the AblyBaseComponent using a call to super();
.connectedCallback
to configure the chat application. We call super.connectedCallback
to trigger all of the Ably configuration logic from the base component. The following code goes below constructor
, inside the closing bracket of the AblyChat
class:super.subscribe* *
function that was defined on the base to subscribe to messages on a channel called chat
. The rest of the parameters, as we pointed out earlier, are standard Ably JavaScript SDK parameters – we’re subscribing only to messages on the topic chat-message
. When a message is received, we call a function called this.onAblyMessageReceived
(which we’ll implement in a moment), passing the received message as an argument.connectedCallback
, we will generate a random string and assign it to a property called id
:renderTemplateAndRegisterClickHandlers
, which we’ll look at shortly.this.inputBox
that is generated when the template is rendered, so that people using the chat UI will be able to instantly start typing.attributeChangedCallback
to update the innerHTML of the chat bubbles in the chat window when messages are received. When an attribute is changed, the innerHTML
of this.chatText
is set and scrolled into view. We’re using a function called formatMessages
, which takes the message history, and converts it to HTML elements fit for display:renderTemplateAndRegisterClickHandlers
function, which is named for what it does! The start of this function calls another function called defaultMarkup
, that takes a single parameter – the *id *of the element, and returns the innerHTML we want to display on the screen – an empty chat box element.querySelectorAll
to find the chatText, inputBox, sendButton, and messageEnd elements so that we can use them in our code:onAblyMessageReceived
function earlier when we subscribed to Ably messages – this function takes the current message history from this.messages
, makes sure it is at most 199 messages long, and adds the latest message to the end of the array:this.messages
, which triggers the UI to re-render because this.messages
is an observed property.sendChatMessage
function is called either when Enter is pressed, or when the button to send a message is clicked. Because we’re extending the AblyBaseComponent, it calls the super.publish
function, passing the channel name and the Ably message payload:handleKeyPress
function is triggered on each keypress. If the keypress is the Enter key and there is a message in the chat box, it sends the chat message:formatMessages
function is responsible for mapping the Ably message history into span elements. There’s a little bit of logic here to detect whether or not the message was sent by the current user of the app by checking the message.connectionId
property against the ably.connection.id
property, and adding a me
or other
CSS class that can apply styles to. The data
property from the message is used to carry the received text message.uuidv4()
function – which generates a unique id
for the component:defaultMarkup
which takes a single parameter – the ID of the component – and uses it to set the id
property on the generated HTML.id
property, we can embed CSS that is scoped specifically to this element ID directly into the output code. This means that if multiple instances of the custom element appear on the same page, they won’t have conflicting ids or styles.div
for holding message history, and a form
for capturing user input, complete with the class names used in our query selector calls earlier. customElements.define
to register the HTML tag: Ably.Realtime
client passing your Ably API key from process.env.ABLY_API_KEY.client.auth.createTokenRequest
to generate a temporary token, and return it back to the client.data-get-token-url
parameter when you use your component in the HTML, but we still have some more setup to do!) process.env.ABLY_API_KEY
. You will need to generate a new ably API key and then define this environment variable, with it’s key value in the AWS UI (or using an automation tool of your preference).Search for Amplify in the Services search bar and click on the resulting AWS Amplify link.
Scroll down the resulting page to "Host your web app, and click on "Get started":
Edit your build settings to include npm run ci
as a prebuild command and set the baseDirectory to "/build".
If all is well, the component will provision, build, and deploy successfully. The UI will provide you with a URL to view your hosted component.
27