sasproul
sasproul

Reputation: 33

bootstrap-vue N b-form-radio on a page, how to implement v-model

bootstrap-vue

server side/JSON is sending me the N categories for radio button groups. Users will be asked to rate each category as a priority, high, medium, low. I can dynamically generate radio button groups for each category, offering the user to rate the priority.

Based on the N input scenario, how do I generate/allocate/declare/initialize the N individual v-model data variables that I need for each of the N categories, to store the users selection?

I have tried to allocate an array "prioritySelected" in the data section

  data() {
    return {     
      prioritySelected: [],      
    };
  },

and then created() calls loadFormData(). In loadFormData(), based on the incoming JSON, looped thru and created the N entries I need in prioritySelected

    for (var i = 0; i < msnVals.length; i++){
        this.prioritySelected[msnVals[i].type] = '';
      }

and then set v-model to

    <div v-for="item in priorityRank" :key="item.value">
              <b-form-radio
                size="sm"
                style="font-size: 10px"
                v-model="prioritySelected[item.type]"
                :aria-describedby="ariaDescribedby"
                name="item.type"
                :value="item.value"
                >{{ item.text }}
              </b-form-radio>
           
            </div>

Didnt work, thoughts?

Upvotes: 2

Views: 1338

Answers (2)

sasproul
sasproul

Reputation: 33

this is how I solved this issue.

I googled like crazy and didn't find my answers so I asked this question last week. I appreciate the attention but didn't receive a reply I could use. I have since come up with an answer, so I wanted to post - not only to assist anyone else, but to also solicit feedback and further inspiration.

I have 5 accordions. Each accordion has between 5 and 15 sub accordions. Each sub accordion has 3 radio button groups. 129 radio button groups in total. Pic of one of these 'trifectas'. 5 of these, 5-15 sub accordions each, 3 radio button groups each

Each sub accordion radio button group is the same, pick your priority for 3 different categories. The Accordion sections and sub accordion sections come in from the server so I wanted to assemble this area dynamically. The stumbling block was that name and id needed to be unique.

I made a component for the radio button group. I pass in the options array so I can display whatever items I want to. Because I don't care what name and/or ID is, I used UUID to generate the name and ID - this ensues that each radio button group is unique and behaves independently, meaning that the data variable 'selected' only applies to "this" component. Once the user selects a radio button I emit that information up to the parent with enough details so that I know which accordion/sub accordion/group the value came from, and can store it.

I can clear all 129 radio button groups via the refs tag and by looping thru using the length of the refs array and calling the child onClear()function for each.

Here is my (child) component. Thoughts, feedback, etc appreciate

<template>
  <b-form-group
    :label="label"
    v-slot="{ ariaDescribedby }"
    label-align="left"
    label-size="sm"
  >
    <b-form-radio-group
      ref="radioForm"
      :id="uuidv4()"
      v-model="selected"
      :options="options"
      :aria-describedby="ariaDescribedby"
      :name="uuidv4()"
      stacked
      @change="onSelectRadioButton"
    ></b-form-radio-group>
  </b-form-group>
</template>
<script>
export default {
  name: "RadioComponent",
  props: {
    component: {
      type: String,
      default: null,
    },
    subComponent: {
      type: String,
      default: null,
    },
    label: {
      type: String,
      default: null,
    },
    options: {
      type: Array,
      default: null,
    },
  },
  data() {
    return {
      selected: "",
      reply: {
        component: this.component,
        subComponent: this.subComponent,
        label: this.label,
        item: [],
      },
    };
  },
  methods: {
    onSelectRadioButton(value) {
      this.reply.item = [];
      this.reply.item = this.options[value];     
      this.$emit("selected", this.reply);
    },
    onClear() {
      this.selected = [];
    },
    /**
     * function to generate UUID
     */
    uuidv4() {
      return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
        (
          c ^
          (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))
        ).toString(16)
      );
    },
  },
};
</script>

This is what it looks like to call the component from the parent, with the child emit to 'selected' calling the parents radioButtonSelected method. This snip is actually embedded in several loops as I am reading the information from a json file that contains the categories (the item variable) and sub categories (the entry variable). I would think this same approach could be used for groups of checkboxes

<b-collapse :id="'accordion-' + entry.id" role="tabpanel">
                <b-row
                  style="
                    padding-left: 20px;
                    padding-top: 4px;
                    padding-bottom: 4px;
                  "
                >
                  <b-col cols="4" style="font-size: 10px">
                    <PriorityRadioButtons
                      ref="radioBtnComponent"
                      label="PRIORITY"
                      :component="item.type"
                      :subComponent="entry.text"
                      :options="options"
                      @selected="radioButtonSelected"
                    />
                  </b-col>
                  <b-col cols="4" style="font-size: 10px">
                    <PriorityRadioButtons
                      label="RISK"
                      ref="radioBtnComponent"
                      :component="item.type"
                      :subComponent="entry.text"
                      :options="options"
                      @selected="radioButtonSelected"
                    />
                  </b-col>
                  <b-col cols="4" style="font-size: 10px">
                    <PriorityRadioButtons
                      label="PROXIMITY"
                      ref="radioBtnComponent"
                      :component="item.type"
                      :subComponent="entry.text"
                      :options="options"
                      @selected="radioButtonSelected"
                    />
                  </b-col>
                </b-row>
              </b-collapse>

Upvotes: 1

rawstream
rawstream

Reputation: 61

It seems that your initial prioritySelected property should be an object instead of an array.
Then you could add the properties like you do in the loop.

Upvotes: 0

Related Questions