Can I read a Rails database from within a Stimulus controller?

Hello! Rails and Stimulus/Ajax beginner here, and I was hoping someone might have some advice to get me unstuc…

I’m making an online Invoicing app, and have an Invoice form, which also uses nested Lineitem partials inside of it. In each nested Lineitem, you can select a “Billable” name , which derives from my Billable model. My Billable model has three attributes: Name, Price and Comment. The user sets these up before making an invoice….

Anyway, when the user selects a Billable name from the Lineitem’s drop-down menu (for instance “Sound “Recordist or “Microphones” or “Meals”), I want to use Stimulus to automatically populate the Lineitem’s Price and Comment input fields with the data from the selected Billable’s Price and Comment attributes (which act as defaults).

Any idea how to best go about this? I can use Stimulus to read my drop-down’s Billable ID, but I can’t seem to find anything about reading a model’s database attributes from within a Stimulus controller (so I can look up the Billable’s other attributes—price and comment). I’ve looked at some concepts like Stimulus Hovercards but the examples are able to call up database info from the Rails environment before sending it to Stimulus for DOM rendering, whereas I can’t know what Billable record to look up until I’m inside the Javascript controller, and then I’m in Javascript. Or that’s what I think, at least. :wink:

Any advice much appreciated, thanks!

PS Attaching a visual cue to help understand what I’m trying to do…

1 Like

Hi k2director,

You could add an event listener to your select and then fetch data from a Rails action.
If you set the id as the value of your select options.

<select data-action="change->my-controller#selectHandler">

You can do something like:

selectHandler(e) {
 let id = e.target.value;
 fetch(`/controller/action/${id}`)
 .then((response) => response.json())
 .then((data) => doSomethingWithYourDataHere(data));
}
1 Like

Thank you for the response, Sgroen, it’s much appreciated!

I tried out the Javascript function, and can read the ID of whatever Billable item I select from the dropdown, and then Fetch on that (for instance…/billables/8) but I can’t seem to get access to the Response or the Data it’s supposed to be fetching. I keep getting an error about “Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0”

Here is my code, where you can see I’m just trying to console.log ‘data’ (replacing your “doSomethingWithYourDataHere(data)” line), just to see what’s there. I’ve also tried to console.log ‘response’ but it’s undefined.

selectHandler(e) {
    let id = e.target.value;
    fetch(`/billables/${id}`)
        .then((response) => response.json())
        .then((data) =>
        console.log(data));
}

Any further thoughts? One thing I wondered about is that I’m not Fetching on billables/show/id, because that kept producing an error. I’m fetching simply on billables/id, since that’s the URL where you find the Billable record I’m looking for.

Thanks!!

Hi @k2director,

The error Unexpected token in < in JSON at position 0 often means the JavaScript code was trying to retrieve and parse JSON, but received an HTML response instead. The “<” token refers to the first character in an HTML response, usually starting with <!DOCTYPE html>.

If you look in the Network tab of your browser, specifically at the response given by the request to /billables/:id, you should see the HTML response, which should have been JSON instead.

In your BillablesController, you may need to ensure that def show is responding with JSON, something like this:

  respond_to do |format|
    format.html
    format.json # <!-- make sure you have format.json, in addition to html 
  end

Hopefully that helps!

Sgroen, cancel that last message, I got it working!

I realized that I probably needed to create a custom Rails controller action for what I wanted to do, and then a route for it. So I did that, and just added a “render json: @billable…” line in my custom controller action, and things started to work.

So THANK YOU for turning me on to Fetch. This will definitely be useful in the future…

2 Likes

No problem happy to help :wink: