Pointers on a Stimulus conditional select
I am walking through this (https://stimulusjs.org/handbook/hello-stimulus) and I am seeing how powerful Stimulus is. I have a basic controller built and can tigger events (basic alerts etc.) to test drive this.
Intermediate questions for the experts:
Intermediate questions for the experts:
- Can you add nested folders to organize your controllers? I can see this getting messy.
- Can you use CoffeScript and JQuery here also? Plain JS just seem so clunky after using them.
I see where this is going what I don't get is how I pull the query from the DB and update the target select. I know there are the Rails reponds_to JS controllers that do similar results like
Chris Oliver
does here https://gorails.com/episodes/nested-comment-threads-in-rails-part-3?autoplay=1.
I just don't get yet how you combine Stimulus with the Rails Active Record calls etc.
I just don't get yet how you combine Stimulus with the Rails Active Record calls etc.
Soooooooooo close. It works except that my dynamic select populates twice like this:
- item 1
- item 2
- item 3
- item 1
- item 2
- item 3
Can anyone see what I am missing? The whole controller is not being run twice because the existing contents are wiped clean on the first line. It's in that 'request.onload' function that seems to be looping twice somehow.
I have a custom controller action that does the JSON via jbuilder:
related.json.jbuilder
json.array!(@related) do |exp| json.extract! exp, :id json.extract! exp, :related_select_label end
custom related controller action
def related if params[:vendor_id].nil? && params[:budget_id].nil? @related = [ { } ] else @related = Expenditure.includes(:budget, :vendor, :project).where(flag_active: true).where( vendor_id: params[:vendor_id], budget_id: params[:budget_id] ) end respond_to do |format| format.json #{ render :json => @related.to_json } end end
I added some logic to confirm the input has values
_form.html.erb
<div data-controller="expenditure"> <%= form_with(model: expenditure) do |form| %> <div class="form-group"> <%= form.label :category %> <%= select(:expenditure, :category, [ [ "Purchase Order" , :purchase_order ],[ "Work Order", :work_order], [ "Invoice", :invoice ], ["Accrual", :accrual ], ["Field Ticket", :ticket ] ], {class: "form-control"} , { data: { target: "expenditure.category", action: "change->expenditure#update_related"} } ) %> </div> <div class="form-group"> <%= form.label :budget_id %> <%= collection_select(:expenditure, :budget_id, @budgets, :id, :select_label_client, {include_blank: 'Select a budget...'}, {class: "form-control", data: { target: "expenditure.budget" ,action: "change->expenditure#update_related"} } ) %> </div> <div class="form-group"> <%= form.label :vendor_id %> <%= collection_select(:expenditure, :vendor_id, @vendors, :id, :name, {include_blank: 'Select a vendor...'}, {class: "form-control", data: { target: "expenditure.vendor" ,action: "change->expenditure#update_related"} } ) %> </div> <div class="form-group"> <%= form.label :parent_id %> <%= collection_select(:expenditure, :parent_id, @related, :id, :related_select_label, {include_blank: 'Select a parent expenditure...'}, {class: "form-control", data: { target: "expenditure.related"} } ) %> </div> </div>
now the magic!... HT to https://www.codebyamir.com/blog/populate-a-select-dropdown-list-with-json
expenditure_controller.js
import { Controller } from "stimulus" export default class extends Controller { static targets = [ "category", "budget", "vendor", "related" ] update_related() { let dropdown = this.relatedTarget; dropdown.length = 0; let defaultOption = document.createElement('option'); defaultOption.text = 'Select parent expenditure...'; dropdown.add(defaultOption); dropdown.selectedIndex = 0; const url = '/related_expenditures.json?vendor_id=' + this.vendorTarget.value + '&budget_id=' + this.budgetTarget.value; const request = new XMLHttpRequest(); request.open('GET', url, true); request.onload = function() { if (request.status === 200) { const data = JSON.parse(request.responseText); let option; for (let i = 0; i < data.length; i++) { option = document.createElement('option'); option.value = data[i].id; option.text = data[i].related_select_label; dropdown.add(option); } } else { // Reached the server, but it returned an error } } request.onerror = function() { console.error('An error occurred fetching the JSON from ' + url); }; request.send(); } }
Don't have time to replicate your whole code, but I am doing something similar with json and using this
Rails.ajax({ url: "/notifications.json", type: "get", data: "", success: function(data) {} error:function() {})
And it is working well, maybe this way could help with the double unload event
Notifications
You’re not receiving notifications from this thread.