samuel toh
samuel toh

Reputation: 7076

How can I unify text that take from multiple group radio button? (vue.js 2)

My vue component like this :

<template>
    <div>
        <div class="col-md-4">
            <ul class="list-unstyled">
                <li><strong>England</strong></li>
                <li>
                    <div class="checkbox">
                        <label>
                            <input type="radio" name="england" class="radio"> Chelsea
                        </label>
                    </div>
                </li>
                <li>
                    <div class="checkbox">
                        <label>
                            <input type="radio" name="england" class="radio"> Mu
                        </label>
                    </div>
                </li>
                <li>
                    <div class="checkbox">
                        <label>
                            <input type="radio" name="england" class="radio"> Arsenal
                        </label>
                    </div>
                </li>
            </ul>
        </div>
        <div class="col-md-4">
            <ul class="list-unstyled">
                <li><strong>Spain</strong></li>
                <li>
                    <div class="checkbox">
                        <label>
                            <input type="radio" name="spain" class="radio"> Madrid
                        </label>
                    </div>
                </li>
                <li>
                    <div class="checkbox">
                        <label>
                            <input type="radio" name="spain" class="radio"> Barcelona
                        </label>
                    </div>
                </li>
                <li>
                    <div class="checkbox">
                        <label>
                            <input type="radio" name="spain" class="radio"> Atletico
                        </label>
                    </div>
                </li>
            </ul>
        </div>
        <div class="col-md-4">
            <ul class="list-unstyled">
                <li><strong>Italy</strong></li>
                <li>
                    <div class="checkbox">
                        <label>
                            <input type="radio" name="italy" class="radio"> Juve
                        </label>
                    </div>
                </li>
                <li>
                    <div class="checkbox">
                        <label>
                            <input type="radio" name="italy" class="radio"> Milan
                        </label>
                    </div>
                </li>
                <li>
                    <div class="checkbox">
                        <label>
                            <input type="radio" name="italy" class="radio"> Inter
                        </label>
                    </div>
                </li>
            </ul>
        </div>
        <span id="result-select">Result</span>
    </div>
</template>

<script>
    export default {
        props: ['...'],
        ...
    }
</script>

My javascript code like this :

$('input[type="radio"]').click(function(){
    var $radio = $(this);
    var name = $(this).prop("name");

    // if this was previously checked
    if ($radio.data('waschecked') == true)
    {
        $radio.prop('checked', false);
        $radio.data('waschecked', false);
        $('#result-select').text('');
    }
    else{
        $radio.data('waschecked', true);
        $(`input[name=${name}]:not(:checked)`).data('waschecked', false);
        $('#result-select').text(txt);
    }

    let output = [];
    var txt;
    $('input[type="radio"]:checked').each( function() {
            txt = $(this).parent().text();
            output.push(txt);
    });
    $('#result-select').text(output.join(' - '));
});

I still use javascript to unify each selected radio button group. This javascript code is working fine. But I want to change it using vue component. So there is no javascript code. But I am still confused

I will explain the plot first

I want to :

If I select chelsea, madrid and juve the result like this :

Chelsea - Madrid - Juve

If I select chelsea and madrid the result like this :

Chelsea - Madrid

So if I check radio button, it display the text. If I uncheck radio button, it not display the text

How can I do it in vue component?

Update :

The radio button can be unchecked

For example :

If I select chelsea, madrid and juve the result like this :

Chelsea - Madrid - Juve

Then I uncheck madrid, the result like this :

Chelsea - Juve

Upvotes: 0

Views: 213

Answers (2)

Roy J
Roy J

Reputation: 43881

Any time you need a value based on other values, you should look at using a computed. In this case, a computed that goes through the country data and picks out the selected city names and returns them as a list.

  computed: {
    selecteds() {
      return this.countries
        .map(c => c.selected)
        .filter(s => s);
    }
  },

Check-and-uncheck functionality is supplied by v-model on the radio inputs. If the value of what is bound to v-model matches the value bound to value, the button is checked; if not, not.

I used a settable computed to handle the case where you're clicking an already-clicked button. If it is already selected, set the value to null to unselect it. Because I'm in a component, "set the value to null" is done by emitting an event that the parent uses to set the value.

computed: {
    proxySelected: {
      get() {
        return this.data.selected;
      },
      set(newValue) {
        this.$emit('update', this.data.name, this.data.selected === newValue ? null : newValue);
      }
    }
  }

function countryData(name, cities) {
  return {
    name,
    cities,
    selected: null
  };
}

new Vue({
  el: '#app',
  data: {
    countries: [
      countryData('England', ['Chelsea', 'MU', 'Arsenal']),
      countryData('Spain', ['Madrid', 'Barcelona', 'Atletico']),
      countryData('Italy', ['Juve', 'Milan', 'Inter'])
    ]
  },
  computed: {
    selecteds() {
      return this.countries
        .map(c => c.selected)
        .filter(s => s);
    }
  },
  methods: {
    update(countryName, newSelectedValue) {
      this.countries.find(c => c.name === countryName).selected = newSelectedValue;
    }
  },
  components: {
    country: {
      template: '#country-template',
      props: ['data'],
      data() {
        return {
          checked: []
        };
      },
      computed: {
        proxySelected: {
          get() {
            return this.data.selected;
          },
          set(newValue) {
            this.$emit('update', this.data.name, this.data.selected === newValue ? null : newValue);
          }
        }
      }
    }
  }
});
.list-unstyled {
  list-style: none;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="app">
  <country v-for="country in countries" :data="country" @update="update" :key="country.name"></country>
  <div>{{selecteds.join(' - ')}}</div>
</div>

<template id="country-template">
  <div class="col-md-4">
    <ul class="list-unstyled">
      <li><strong>{{data.name}}</strong></li>
      <li v-for="city in data.cities">
        <div class="checkbox">
          <label>
            <input type="radio" :name="data.name" class="radio" :value="city" v-model="proxySelected">
            {{city}}
          </label>
        </div>
      </li>
    </ul>
  </div>
</template>

Upvotes: 2

user7995820
user7995820

Reputation: 442

Use v-model to do this: <input type="checkbox" v-model="italy">

And add vue will create an array for italy which you can output in your vue template like {{ italy.join(' - ') }}

Upvotes: 0

Related Questions