Summary

We are going to build an alarm clock app using AlpineJs. It's a simple web app where we will be creating alarms and managing them using Alpinejs. We will not be working with any server API's its purely a frontend app using plain javascript and Html

Project Structure

As you can see we have created a folder with the project name alarm_clock_alpinejs.

We have created index.html and placed alarm_sound.mp3 in root project and an alarm.js in the js directory

Technology Description

Alpinejs is a microframework to say precisely. It does provide and functionality of React/Vue in a very simple way. All you need to just import the js file and start working on it.

I have a 3 to 4 yrs of working experience in React.

I clearly see the need for this library for smaller web-pages or server-side interactive landing pages which are driven from webhooks or external redirects.

You can use it there for smaller needs without thinking instead of going a heavy way of using any template engine (Jinja/JSP/EJS). I have worked in them. But yes this library fills all our needs for sure for these purposes

Implementation

We will start the implementation with our index.html and learn the written code section by section.

Guideline to learn via this blog

Understand through code is a very optimal way of figuring out the new stack you come to know why and how tasks are being completed via code and use the relatively in your own projects. Implementation and successful run gives you more clarity of how it works The best way is to start writing instead of cloning the project Yes you can have your own way so go-ahead

index.html

The final implemented screen will look like below

Complete Index.html code

Imports

Let’s see head section

Clearly you can see we have included below js in our index.html file

<script nomodule src="https://unpkg.com/browser-es-module-loader/dist/babel-browser-build.js"></script>

<script nomodule src="https://unpkg.com/browser-es-module-loader"></script>

We have imported babel and the es6 module. Yes we will be using es6 syntax it is cleaner and very efficient. More you can find in this link https://babeljs.io/setup#installation go there and see es6 if you haven’t been in tough till yet

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>

We have imported momentjs library. Yes, we are building a digital clock in the app. We will be needing a more time util library to deal with it MomentJs is the best option. For more details go to https://momentjs.com/docs/

<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js" defer></script>eff

Alpinejs. Its the main library we are trying to implement go to https://github.com/alpinejs/alpine. for details

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous" />

Now we need to use some kind of CSS library we will be using bootstrap-4. We have bootstrap CDN. Go to https://getbootstrap.com/docs/4.4/getting-started/introduction/ for better understanding of bootstrap

<script src="js/alarm.js"></script>

Finally, our own js file alarm.js is imported which we will use to implement our own code in alpinejs to hand interactive tasks

HTML Code/JS implementations

<div class="container" x-data='loadAlarmConfig()' x-init='() => {statTimer();}'></div>

Now inside our code in body tag we have parent div. We have given class container-md to parent div

Let’s look at the code of alarm.js

Tags:

x-data → Now in this attribute we have called loadAlarmConfig() function which is returning a js object with all data and functions we will be needing in our code. After getting this global object from this function we can access each variable and function in child html nodes using various attributes (x-text, x-model, x-bind etc).

As an example in return of loadAlarmConfig() a variable time and respective function like statTimer/createAlarm which we can directly call in child nodes using AlpineJs directives

x-init→

Now this a big virtue of AlphineJS. It is a must-have attribute we all need on various occasions. As we will call x-init to initialize objects and variables to use inside dom elements.

There are several things we need to do (API calls/Window onnload functions etc). Which we can call here. Inside the object returned from loadAlarmConfig() we have created a function statTimer(). Which is updating current time values in time object inside our global object.

We can directly call this function inside x-init

x-init='() => { statTimer(); }'

Call to x-init function is very simple startTimer function is available after getting it via loadAlarmConfig in x-data

function updateClock() {

self.time.hour = moment().local().format("h");

self.time.minute = moment().local().format("m");

self.time.second = moment().local().format("s");

self.time.a = moment().local().format("A");

} setInterval(() => {

updateClock();

}, 1000);

Inside startTimer we have saved current object instance in self. As some Async function is written inside setInterval(). in every 1000 milliseconds we are calling upateValue() function and updating time object inside the global object.

time: {

hour: moment().local().format("h"),

minute: moment().local().format("m"),

second: moment().local().format("s"),

a: moment().local().format("A"),

},

Above is the time object which we have created globally

Part-1 Display Alarm Clock

Now, let's start by displaying our clock first. We need to show the current clock

Here the x-text function is used to display time object values. These variables are getting auto-updated in function startTimer we have explained it already. It will update time in real-time we have called updateClock function at every 1 second. When you will open index.html you can see it getting updated

(Create Alarm) Button

Yes the main important part of our project. Create an alarm button

<button class="btn btn-info" @click="createAlarm()">Create Alarm</button>

Yes we can see we have configured click event and call createAlarm function in our global object

createAlarm: function() {

this.create_alarm = true;

this.alarm = {

"hour": this.time.hour,

"minute": this.time.minute,

"second": this.time.second,

"title": "",

"a": this.time.a

};

},

This is our function inside the global object in alarm.js. We are setting current global object create_alarm to True. And pre-populate values inside the current alarm object which show that we can autofill current time values while creating a new alarm.

That’s it. In this way you can configure click event easily. When we will click on create alarm below UI Is getting populated

Part-2 Create Alarm Code

Now its a code for creating alarm

<div class="col" x-show="create_alarm"></div>

In this parent div component. We have x-show=’create_alarm” look at js code of createAlarm we have set a global variable create_alarm. when it is true we show create alarm div. Otherwise its display is set to none. Very simple…

In the reset code we are using x-model to bind alarm object attributes to inputs. x-model building a two-way interaction whatever changes we will do in these input types they will be synced automatically to their respective x-model definitions.

<input placeholder="Type alarm title here" type="text" x-model="alarm.title" class="form-control">

Just example we have set alarm.title to this input text box. Whatever we will type will be synced automatically to alarm.title variable. Easy

Action Button



< i class="fas fa-check"> < /i>

< /button> < button class="btn btn-dark" @click ="saveAlarm()">< i class="fas fa-check"> < /i>< /button>

Let’s see what we are doing in saveAlarm function in alarm.js

In this code at initial steps, we have done some validations if alarm title is empty or alarm time is wrongly set we will show them error respectively

Next we will create alarm settings time_left and alarm start_time for alarm and set create_alarm false.

Finally when we are done creating alarms. We will push current alarm to alarms global array and see we have used copyObject so that reference of current temporary alarm object is removed

Par-3 Displaying Alarm

As we pushed created alarm to global alarms array. Below code will show our newly created alarm as we have

<template x-for="item in alarms" :key="item"></template>

Setting text values for display. We are showing alarm label and time_left in x-text attribute and setting their respective values from the alarm object inside alarms array

<div x-bind:class="getAlarmClass(item)"></div>

We are controlling the display of the current alarm container. let’s look at the code of getAlarmClass

getAlarmClass: function getAlarmClass(item) {

if (!item.active) {

return "card mt-3 bg-dark text-white ";

} else if (item.completed) {

return "card mt-3 bg-warning text-white";

} else {

return "card mt-3 bg-light"

}

}

We are deciding alarm card theme here based on the current alarm status. It will become dark if gets deactivated and yellowish in case it is ringing and light if it is active

Stop alam action button



Stop

</button> @click ="deactivateAlarm(item.index)" class="btn btn-danger">Stop

We are checking if the alarm is active we show this button and on click, we will be calling deactivateAlarm function with current alarm index

deactivateAlarm: function(item) {

this.alarms = this.alarms.map((alarm) => {

if (alarm.index === item) {

alarm.completed = true;

alarm.active = false;

alarmSound.pause();

}

return alarm;

})

}

Part 4 Running Alarms in background

We need to iterate all alarms one by one in our global object. Check and update each and every alarm status

Now these alarms will run automatically after getting pushed in to global object.

Code to integrate global alarm array is writing inside statTimer which we have called at parent div x-init

We are calling a runAlarms function every 2 milliseconds and iterate over each alarm and set their status respectively and run alarm sound as they get completed.

This is a basic tutorial I hope you will get a glimpse of what we can achieve with this library. I hope you will find it useful and we'll be able to utilize in many scenarios

Find GitHub code link

https://github.com/rakeshbhatt10/demo_alam_clock_alpinejs

Happy coding