Making a conditionnal form using Rails & Stimulus

360 Views Asked by At

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.

  1. Player gives input B to the question 1
  2. I check the value of the question 1 input
  3. If the value is A, I show the question 1-A
  4. 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")
    }
  }
}

0

There are 0 best solutions below