Update on Near API JS with Rails

0 55
Avatar for wabinab
2 years ago

Just an update on the previous article on Rails with NEAR-API-JS; we didn't manage to make the frontend and backend works fine. In fact, we have two buttons for login and logout existing concurrently, and a third button to click and check whether you have logged in or not. Then, a fourth button to first login, and click on that fourth button to save user to database. With something on the database, then user can only direct to the page. If user not on database, they don't have a page. Sounds bad with so many buttons?

One thought, we could use js.erb files, just like html.erb files, to work with rendering on the backend, and redirect to js.erb to do the javascript work. It fails; not because one did it wrong, but because one uses Rails 7. After there are some issues (security issues or something, one isn't sure) found on Rails 6 with js.erb, it's deprecated, and Rails 7 locked it so if you did what you did in Rails 6, it won't redirect to the js.erb file; in fact, nothing would happen. It only responds to the others html.erb (if you have one).

As a replacement, Rails 7 have Hotwire Stimulus (which one chose to ignore for the earlier part when one is studying Rails) for js.erb. This locates in the app/javascript/controller folder, which one chose to ignore till now. And checking this article, experimenting with it, one finally found out how to use it. With Hotwire Stimulus, we could do frontend design while calling frontend javascript (on near-api-js functions) at the same time, without having to go back to backend. The controllers does its job on the frontend (seemingly). (How exactly it works, one don't know, and one don't really care unless there's security issues like sending unencrypted private keys, etc).

Let's take a short look on the technical side. (this is for oneself future reference, feel free to skip, sorry @DrPsycho )

Technical Side

The important thing (and most easiest to understand) in that article is this pieces of code:

// Taken from https://dev.to/bhumi/stimulus-rails-7-tutorial-5a6a
<div data-controller="slideshow" data-slideshow-index-value="1">
  <button data-action="slideshow#previous"> ← </button>
  <button data-action="slideshow#next"> → </button>

  <div data-slideshow-target="slide">🐵</div>
  <div data-slideshow-target="slide">🙈</div>
  <div data-slideshow-target="slide">🙉</div>
  <div data-slideshow-target="slide">🙊</div>
</div>

and this:

// Taken from https://dev.to/bhumi/stimulus-rails-7-tutorial-5a6a
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = [ "slide" ]

  static values = {index: Number}

  initialize() {
    this.showCurrentSlide()
  }

  next() {
    this.indexValue++
    this.showCurrentSlide()
  }

  previous() {
    this.indexValue--
    this.showCurrentSlide()
  }

  showCurrentSlide() {
    this.slideTargets.forEach((element, index) => {
      element.hidden = index != this.indexValue
    })
  }
}

It's difficult to understand without experimenting with it. Basically, there are 2 arrow buttons, upon clicking, called next() or previous() to change to the four monkey face depending on the this.indexValue.

Talking first about the html.erb code, we note that to connect to a controller, we need a div defining the data-controller (must be same name). Here, it's slideshow so the controller name must be slideshow_controller.js under the app/javascript/controller folder. Then, we can (or choose not to) define an init value via data-slideshow-index-value. This correspond to:

static values = { index: Number }

that "index". If you have another thing like this:

static values = { current: String }

We could set the data-slideshow-current-value=some_string on the div.

Then we have the data-action="slideshow#next" which calls the next() function inside the javascript, if this button is clicked. It could also be an a href tag.

Next, is data-slideshow-target="slide". This means we call slideshow controller (if it's a login controller, it's data-login-target), and we put these elements enclosed within this div into the array called slide. WE can see the array here:

static targets = [ "slide" ]

We could add other values and assign them other values, if we need to separately control them.

Let's look at the javascript controller:

The initialize() will be called whenever the website load, so anything that needs a value immediately could put here. If we didn't specify a value in data-slideshow-current-value because we need some value from frontend which we can't determine with backend, we could also mix .js output here, by putting it into the window argument (window is a universal argument that makes your variable assigned to it be discoverable anywhere within the browser, hence global variable).

Notice that for the values, we have the singular this.indexValue. In fact, for each variable inside, like the current: String we spoke about, it will have this.currentValue. These are not discoverable explicitly, but implicit rules.

It's the same for the targets, here we have slide so its this.slideTargets (plural because there is a list of targets). If we have other name, we'll have this.<name>Targets too!

That's it for today!

Conclusion

Well, there's not really a conclusion. This is indeed quite technical. One is happy we found a way to control frontend without relying on backend after a few weeks of searching and pain.

Like and Subscribe?

3
$ 0.66
$ 0.62 from @TheRandomRewarder
$ 0.04 from @DrPsycho
Sponsors of wabinab
empty
empty
empty
Avatar for wabinab
2 years ago

Comments