I'm a newbie in computer development, I have started using Ruby on Rails framework with Stimulus to add some dynamic elements to my pages.
Context
I am working on a video game recommendation system, to do so the player will have to answer a detailled list of questions. To be as pertinent as possible, I would like to make some conditional questions.
Example : You answer "B" to question 1, the next question is 1-B You answer "A" to question 1, the next question is 1-A, and so on.
How to do it
After some research, it seems that the best practice to do so would be to have a massive form with every input and to show/hide the ones depending of the values.
- Player gives input B to the question 1
- I check the value of the question 1 input
- If the value is A, I show the question 1-A
- If the value is B ...
The problem
So far, I managed to get to the point 3. but with some issues.
When I'm using the simple_form :collection attributes which gives a drop-down menu, I manage to access the input value in the list using the Stimulus target "input".
The not-so working version with a collection:
However, if I change the input type to "radio_boxes" I can only access the first value in the collection.
The not working version with a radio_buttons type for the input
I guess my problem is located in the JS controller, would be awesome if you had any idea regarding this issue!
My code
I have two tables, a player and a personnality which belongs to a player :
Player model:
class Player < ApplicationRecord
belongs_to :user
validates :user, uniqueness: true
has_one :personality, dependent: :destroy
accepts_nested_attributes_for :personality
end
Personnality model:
class Personality < ApplicationRecord
belongs_to :player
validates :player, uniqueness: true
SATURDAY_NIGHT_QUESTION = "It's Saturday night, you are probably"
SATURDAY_NIGHT_ANSWERS = [
"Staying at home",
"Going out"
]
SATURDAY_HOME_QUESTION = "Alright, comfy Saturday at home sounds good!, what do you do there?"
SATURDAY_OUT_QUESTION = "Alright, party time then! Where are we headed to?"
SATURDAY_HOME_ANSWERS = [
"Reading a book",
"Playing online with some friends"
]
SATURDAY_OUT_ANSWERS = [
"Going to a bar of course",
"A friend is having a boardgame session"
]
end
I have put my questions & answers in my models to centralize it, in case I will have to edit it afterwards (is it a good idea by the way to put it in the model?).
View
<p>Welcome, player</p>
<div data-controller="sample-dropdown">
<%= simple_form_for(@player) do |f| %>
<%= f.simple_fields_for :personality do |p| %>
<% p.input :player_id, as: :hidden, input_html: { id: p.object.player_id }%>
<%= p.input :saturday_night, label: Personality::SATURDAY_NIGHT_QUESTION,
collection: Personality::SATURDAY_NIGHT_ANSWERS, as: :radio_buttons,
input_html: {data:{target: 'sample-dropdown.input', action:'input->sample-dropdown#answer'}} %>
<div class="disable" data-sample-dropdown-target="test1">
<%= p.input :saturday_action, label: Personality::SATURDAY_HOME_QUESTION, collection: Personality::SATURDAY_HOME_ANSWERS, include_blank: false %>
</div>
<div class="disable" data-sample-dropdown-target="test2">
<%= p.input :saturday_action, label: Personality::SATURDAY_OUT_QUESTION, collection: Personality::SATURDAY_OUT_ANSWERS, include_blank: false %>
</div>
<% end %>
<%= f.button :submit %>
<% end %>
<% console %>
</div>
I am using the simple form gem with Stimulus a small JS framework.
Here is my JS Controller :
mport { Controller } from "@hotwired/stimulus"
// Connects to data-controller="sample-dropdown"
export default class extends Controller {
static targets = ["input", "test1", "test2"]
connect() {
console.log(this.inputTarget)
}
answer() {
const element = this.inputTarget
console.log(element.value)
switch (element.value) {
case "Staying at home":
this.test1Target.classList.remove("disable")
this.test1Target.classList.add("active")
this.test2Target.classList.remove("active")
this.test2Target.classList.add("disable")
case "Going out":
this.test2Target.classList.remove("disable")
this.test2Target.classList.add("active")
this.test1Target.classList.remove("active")
this.test1Target.classList.add("disable")
}
}
}