How to build a Tinder-like view on Forest Admin

In one of our recent articles, we took a look at how to create Moderation Views in Forest Admin with the help of Smart Actions and Smart Views. Today, we’ll take a peek at Tinder-like validation views, another similar tool that you can create on Forest Admin in no time.

Getting started

To start us off, let’s take a look at what Tinder-like validation views are, exactly.

In essence, validation views are not all that different from the moderation views we saw last time: we use Smart Actions and Smart Views to provide a tool for making specific decisions on data, which usually involves a yes or no question.

A prime example is what we’ll be taking a look at today: we’ll draw some inspiration from one of the largest dating apps out there, in that they work on a swipe left or right basis, and let users validate data in it. In our example, you’ll be able to do this using your arrow keys.

The validation view we’re going to build here is going to contain:

  • A clean display of the information we want to validate. In our case, we want to display records from a user one by one, in order to keep everything as straightforward as possible.
  • Easy validation actions to allow fast decisions and prevent too many unnecessary clicks — as noted previously, this will be done using the arrow keys.
  • An automatic switching mechanism that loads the next item to speed up the validation process.

Let’s take a look at these specific components one by one.

A clean display of information to validate

In Forest Admin, records are displayed using table views by default. One row in such a table corresponds to a one-lined record, which is, unfortunately, not ideal for displaying data other than text, such as images or related data.

To give us more space and more room for actions, we’re going to build a different view, which will display the details of one customer at a time.

In our setup, the records themselves will be passed to a Smart View we create as "this.args.records" in the javascript code, so we can use "@records" in our template to use them.

Knowing that we are using ember-data to interact with models, we can also use "@records.firstObject" to retrieve the first record to display in the template. With this in mind, displaying the records attribute is only a matter of HTML. Here is an example.

<div class="wrapper-content">
  <div class="record-container" >
    <div class="c-beta-label c-beta-label--top ember-view l-dmb">
      <div class= "c-beta-label__label">Name</div>
      <p class="c-row-value align-left">{{@records.firstObject.forest-firstname}} {{@records.firstObject.forest-lastname}}</p>
    </div>
    <div class="c-beta-label c-beta-label--top ember-view l-dmb">
      <div class= "c-beta-label__label">Email</div>
      <p class="c-row-value align-left">{{@records.firstObject.forest-email}}</p>
    </div>
    <div class= "row-value-image">
      <img src="{{@records.firstObject.forest-avatar}}" width="300" height="400">
    </div>
  </div>
</div>

Of course, we can customize the view however we want, all we need to keep in mind, is:

  • The records are accessible through "@records" in the template
  • The first record can be accessed using "@records.firstObject" in the template
  • We can display attributes in this manner: "@records.firstObject.forest-my-attribute"

Easy validation actions

In terms of validation, we will need two specific actions to take care of our data:

  • Approve a customer
  • Reject a customer

As these two actions are fairly simple to put together as Smart Actions, we won’t go into too much detail — all they require you to do is set the validation status of a certain record to approved or rejected.

What we do need is an easy way to access these functions once we already have them implemented. For this, we’re going to create a way for us to use both on-screen buttons, and the arrow keys on the keyboard.

Creating our buttons

Triggering Smart Actions — like our approval and rejection ones — in a Smart View is only a matter of calling "triggerSmartAction", already provided in the component. Here’s an example.

@action<div class="wrapper-content">
  <div class="record-container" >
    <div class="c-beta-label c-beta-label--top ember-view l-dmb">
      <div class= "c-beta-label__label">Name</div>
      <p class="c-row-value align-left">{{@records.firstObject.forest-firstname}} {{@records.firstObject.forest-lastname}}</p>
    </div>
    <div class="c-beta-label c-beta-label--top ember-view l-dmb">
      <div class= "c-beta-label__label">Email</div>
      <p class="c-row-value align-left">{{@records.firstObject.forest-email}}</p>
    </div>
    <div class= "row-value-image">
      <img src="{{@records.firstObject.forest-avatar}}" width="300" height="400">
    </div>
  </div>
</div>

As stated in our Smart Action documentation, we just need to pass three argument to this function:

  • The collection we want to apply the Smart Action on
  • The action name we want to execute (in our case either Approve or Reject)
  • The customer’s data we want to affect with it

Let's see what it would look like in practice.

<div onclick={{ action 'triggerSmartAction' @collection 'approve' @records.firstObject}}>Approve</div>
<div onclick={{ action 'triggerSmartAction' @collection 'reject' @records.firstObject}}>Reject</div>

That's it for the buttons! You can place them anywhere you want to validate your data, and the Smart Action will be triggered on every single click.

Doing the same with our arrow keys

To provide the same functionality but with arrow keys instead, we will use basic event handling from the keyboard, directly in javascript. Let's take a look at a code sample from our example to understand what is going on:

...

constructor(...args) {
  super(...args);
  this.eventListener = this._eventListener.bind(this);
  document.addEventListener("keydown", this.eventListener);
}

_eventListener(event) {
  const keyCode = event.key;
  if (['ArrowLeft', 'ArrowRight'].includes(keyCode)) {
    event.stopPropagation();
    event.preventDefault();
    this.triggerSmartAction(this.args.collection, (keyCode === 'ArrowLeft') ? 'reject' : 'approve', this.args.records.firstObject);
  }
}

willDestroy() {
  document.removeEventListener('keydown', this.eventListener);
}

...

As you can see, we have created a global event handler, and we call the "triggerSmartAction" function as we already did before.

In this code snippet, the constructor is responsible for creating the event handler (line 5 to 6). Don't forget to delete the event handler when your component is destroyed (line 19), otherwise it will keep trying to execute on keyboard input and will throw errors due to missing context. This can be done with the "willDestroy" hook.

Automatic switching to the next record

After having performed a validation action, we also need to update our Smart View itself to display the next set of data that needs attention.

The good news is, Forest Admin can handle this behavior by default. Every time we perform an action on a record, Forest Admin refreshes our set of data for us to ensure it is updated. Once a customer has been approved or rejected, they will disappear from the list and will give their place to the following one. Easy as that.

And that’s basically it! Once everything is in place, you should have a working validation view that you can use to handle data like in our example. For an extended look at our example code for Tinder-like views, don’t forget to take a look at our documentation.

If you’ve enjoyed this article and would like to see more detailed explanations of some of our more advanced features, don’t forget to follow us on Twitter, Facebook, and LinkedIn. Until next time!