Designing a regex test feature with Stimulus

We’re building an app that requires users to input a regex. We’d like to build a feature that gives users the ability to test their regex, before saving. The feature will work a lot like Rubular. Users will be able to test their regex against various strings.

This post explains how to build the feature using Stimulus, within a Rails 7 application.

1. Generating a view/controller

First we’ll create a new view/controller, to serve the HTML form. We can use the Rails CLI to generate it:

rails g controller admin index

2. Adding a basic form

The HTML form code can be added to the newly generated view template, app/views/admin/index.html.erb:

1
2
3
4
5
6
7
8
9
<h1>Regex tester</h1>

<div>
  Regex: <input type="text">
  <br />
  Example: <input type="text">
  <br />
  <button>Test regex</button>
</div>

For this tutorial, the form will be very simple. It will comprise of a regex input field, an example string input field and a button to trigger the test process.

3. Adding a Stimulus controller

When the user clicks the button it should trigger some JavaScript. This will be handled by a Stimulus controller. We can create a file under app/javascript/controllers/admin_controller.js and add the Stimulus controller boilerplate:

1
2
3
4
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
}

This logic imports the framework’s built-in Controller class and extend it. This is where the custom JavaScript code can be added.

4. Connecting the form to the Stimulus controller

Right now there is no connection between the form and the Stimulus controller. To connect them, we can add a data-controller attribute to the outer div:

1
<div data-controller="admin">

The Stimulus controller is called admin_controller.js so the data-controller value must be "admin".

5. Adding targets to fields

Stimulus allows us to add ‘targets’ to fields that we want to reference in the controller. This makes referencing fields easier, as opposed to manually searching the DOM.

We’ll add a target for both the regex field and example string field:

1
2
3
4
5
6
7
8
9
<h1>Regex tester</h1>

<div data-controller="admin">
  Regex: <input data-admin-target="regex" type="text">
  <br />
  Example: <input data-admin-target="exampleString" type="test">
  <br />
  <button>Test regex</button>
</div>

Because the controller is admin_controller.js the attribute name must be data-admin-target. The attribute value dictates how these targets are referenced in the controller. We’ll use regex as the value for the first and exampleString as the value for the second.

6 Adding targets to the Stimulus controller

To use targets within the Stimulus controller we must define a targets var:

1
2
3
export default class extends Controller {
  static targets = [ "regex", "exampleString" ]
}

This allows targets to be accessed via this.regexTarget and this.exampleStringTarget.

7. Adding a data action

The last step is to get the form button working. That requires a data-action attribute:

1
<button data-action="admin#test">Test regex</button>

We’ll set the value of data-action to "admin#test" which will invoke a function called test, in the Stimulus controller.

8. Testing with an alert

The final piece of the puzzle is to write the test function, in the Stimulus controller. For now, the function will just call alert():

1
2
3
  test() {
    alert('hello!')
  }

At this point, we can test in the browser. When the button is clicked it will trigger a browser alert. This verifies that Stimulus is wired up correctly

9. Adding regex logic

Now it’s time to add the regex testing logic. We can use JavaScript’s RegExp.prototype.test() to run the test. We can access the regex and test string using their targets:

1
2
3
4
5
  test() {
    const regex = new RegExp(this.regexTarget.value);

    alert(regex.test(this.exampleStringTarget.value))
  }

This logic will alert with true or false depending on whether the regex matches.

10. Adding field color validation

The last thing we need to do is update the function to set the field color based on the outcome of the regex test. We can create a conditional based on the outcome of RegExp.prototype.test() and use that to set the borderColor.

1
2
3
4
5
6
  test() {
    const regex = new RegExp(this.regexTarget.value);

    const regexTestColor = regex.test(this.exampleStringTarget.value) ? "green" : "red"
    this.exampleStringTarget.style.borderColor = regexTestColor
  }

That’s it! The feature is working and can be tested in the browser. The regex test feature now sets the border red/green depending on whether the test passes or fails.