Read Message from Static Website Form using Firebase Realtime Database

Advantages of using Static Website.

To using static website for hosting your homepage have many advantages. The side is loaded fast, it’s cheap or even free to host your side.

If you whant to host a blog you can use Jekyll or Hugo

But there is a problem. Data from the forms, like contact or comment etc, can not be aquired in a good way.

This article describes how you can use the Realtime Database provided by Firebase to save the data and then read them in an Android app.

Create the Database

First we create the database used in Firebase.

  1. The first step is to sign-up to Firebase.
  2. Create a new Realtime Database with security in test mode.

Create a Web Form

Next we create a simple form using html with bootstrap.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
    <title>Static Webside Form</title>
  </head>
  <body>
    <div class="container">
      <form class="mt-4" role="form" >
        <div class="form-group">
          <label for="emailInput">Email</label>
          <input type="email" class="form-control" id="emailInput" placeholder="name@example.com">
        </div>
        <div class="form-ground">
          <label for="subjectInput">Subject</label>
          <input type="text" class="form-control" id="subjectInput" placeholder="Subject...">
        </div>
        <div class="form-group mt-4">
          <label for="messageInput">Message</label>
          <textarea class="form-control" id="messageInput" rows="3"></textarea>
        </div>
        <button type="submit" class="btn btn-primary">Send</button>
      </form>
    </div>
  </body>
</html>

The next step is to initialize firebase. You register under setting in the Firebase console and follow the instruction. The end code will lock somehting like this.

    ...
    </div>
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
    <script src="https://www.gstatic.com/firebasejs/7.12.0/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/7.12.0/firebase-database.js"></script>
    <script type="text/javascript">
      firebase.initializeApp({
        apiKey: "apiKey",
        authDomain: "projectId.firebaseapp.com",
        databaseURL: "https://databaseName.firebaseio.com",
        storageBucket: "bucket.appspot.com"
        ...
      });
    </script>
  </body>
</html>

Finally add a function to send the message and use this function as the form action.

    ...
    <div class="container">
      <form class="mt-4" role="form" action="javascript:onSubmit(emailInput, subjectInput, messageInput)">
      ...
    </script>
    <script type="text/javascript">
      function onSubmit(email, subject, message) {
        firebase.database().ref("message").push().set({
          "timestamp": firebase.database.ServerValue.TIMESTAMP,
          "email": email.value,
          "subject": subject.value,
          "message": message.value
        });
        
        // clear the input.
        $("#emailInput").val("");
        $("#subjectInput").val("");
        $("#messageInput").val("");
      }
    </script>
  </body>
  ...

If you send a message it will show up in your database, you can see it in in the Firebase console under Realtime Database.

App for reading the messages

A simple App reads the messages from the firebase database and show them as a list.

You can register the App in setting in the Firebase console. Follow the instruction for what to add to the gradle build files.

You can read more about how to setup and handel MVVM and Injection in other blog posts.

The message is read in the MessageModel model from the firebase database and update a map containing the message.

database.addValueEventListener(object: ValueEventListener {
    override fun onDataChange(snapshot: DataSnapshot) {
        val recordMap = mutableMapOf<String, MessageRecord>()

        // Read the data from the snapshot
        snapshot.children.forEach {
            val key = it.key
            val timestamp = it.child("timestamp").getValue(Long::class.java) ?: 0
            val email = it.child("email").getValue(String::class.java) ?: ""
            val subject = it.child("subject").getValue(String::class.java) ?: ""
            val message = it.child("message").getValue(String::class.java) ?: ""

            key?.let { messageId ->
                val record = MessageRecord(messageId, timestamp, email, subject, message)
                recordMap[messageId] = record
            }
        }

        // Update the message map.
        messageMap.value = recordMap
    }

    override fun onCancelled(error: DatabaseError) {
        // Show a toast if something went wrong.
        Toast.makeText(application, error.message, Toast.LENGTH_LONG).show()
    }
})

The map is then transformed to an list and then get sorted by its timestamp.

val messageList = Transformations.map(messageModel.messageMap) { messageMap ->
    messageMap.values.sortedByDescending { it.timestamp }
}

The list is then presentation in a RecycleView by binding it to it.

ActivityMainBinding.inflate(layoutInflater).let {
	it.messageList.bindMessageRecordList(this, viewModel.messageList)
	setContentView(it.root)
}

You can find the code for the example at github.