0

I created a form with nested attribute using cocoon gem. When link_to_add_association was clicked, it will append the label and text_field. However, I would want the label name to be dynamic in the sense that the label name for every label will be different. For instance, I would like to have 'A:' as label name for first label, 'B:' for the second label, and so on and so forth. Is it possible to achieve this?

/_mcq.html.erb

<%= f.fields_for :mcq_options do |option| %>
  <%= render 'question_paper_generations/mcq_option_fields', f: option %>
<% end %>

<div><%= link_to_add_association 'Add Option', f, :mcq_options %></div>

/_mcq_options_fields.html.erb

<%= f.label :option %>
<%= f.text_field :option, class: 'form-control' %>
Kenny
  • 11
  • 2

1 Answers1

1

Assuming your nested fields are inside a div "#options"

$(document).ready(function() {

  var next_label = "A";

  def next_char(c) {
    next = "A";
    if (c != "Z") {
      next = String.fromCharCode(next.charCodeAt(0) + 1);
    };
    return next;
  };

  $('#options').on('cocoon:after-insert', function(e, added_option) {
    added_option.find("label").first().text(next_label+":");
    next_label = next_char(next_label);
  });

});

EDIT

To use roman numbers: (taken from: https://stackoverflow.com/a/32851198/3372172). Note. There are comments saying this could not work because objects have no order. You should test it, or choose other implementation (you can find similar solutions in the same link).

$(document).ready(function() {

  var next_label = 1;

  function romanize(num) {
    var lookup = { M:1000,CM:900,D:500,CD:400,C:100,XC:90,L:50,XL:40,X:10,IX:9,V:5,IV:4,I:1};
    var roman = '';
    var i;
    for ( i in lookup ) {
      while ( num >= lookup[i] ) {
        roman += i;
        num -= lookup[i];
      }
    }
    return roman;
  };

  $('#options').on('cocoon:after-insert', function(e, added_option) {
    added_option.find("label").first().text(romanize(next_label)+":");
    next_label++;
  });

});
Pablo
  • 3,004
  • 1
  • 12
  • 19
  • Yes, great answer! In the callback I think you should switch the two lines: first determine `next_label` and then use it. – nathanvda Mar 18 '18 at 09:59
  • Well. It depends if the form starts with at least one option or not. I assumed there were no options so A wood be the first label to use. I store the label to use in next_label, so I increment it after using it. – Pablo Mar 18 '18 at 11:13
  • Ow my apologies, i overlooked that next_label was defined globally. – nathanvda Mar 18 '18 at 13:08
  • Hey, thanks for replying. Another quick question, what if i want to use roman numerals as the label name? @Pablo – Kenny Mar 19 '18 at 00:40
  • @Pablo, I tried your suggestion. The label name changed when it is appended. However, The label name do not work correctly. For instance, the first label name was II and the subsequent label name was IV. Any idea what caused this? – Kenny Mar 20 '18 at 13:57
  • @nathanvda, sorry to disturb. One quick question. I found out the cocoon callbacks always fired twice which caused the `next_label` to increase twice but I have no idea what caused it. Do you have any idea about this? – Kenny Mar 20 '18 at 14:42
  • Last time someone had this, they included application.js twice :P Otherwise, without more info a bit hard to say :) It could also depend on how you define the callbacks (e.g. turbolinks issue). If this does not help, please start a separate question. – nathanvda Mar 20 '18 at 14:53