Vuejs复选框不确定状态

时间:2016-09-15 19:13:21

标签: checkbox vue.js status

我需要的帮助不大。我在世界各地区列出了其中的国家/地区:

Site C

HTML:

{
    'North American Countries' : {
        'countries' : {
            'us' :   { 'name' : 'United States'  } ,
            'ca' : { 'name': 'Canada' }
            .
            .
            .
            .
        }
    },
     'European Countries' : {
         ......
     }
}

我尝试使用复选框构建列表,您可以在其中选择国家/地区。如果选中整个区域的复选框,则会自动检查该区域中的所有国家/地区。如果仅检查区域中的少数国家(不是全部),则需要按区域复选框显示不确定的复选框状态。如何处理?

1 个答案:

答案 0 :(得分:0)

“全选”复选框的常用解决方案是使用computed with a setter。选中此框后,将检查所有子框(通过设置功能)。当子框发生更改时,将重新评估“全选”框(在get函数中)。

在这里,我们有一个转折点:如果子框是混合的,则“全选”框应以某种方式指示。该方法仍然使用计算,但不仅仅是真值和假值,它可以返回第三个值。

没有内置的方式来表示复选框中的第三个值;我选择用阴阳表情符号代替它。

const rawData = {
  'North American Countries': {
    'countries': {
      'us': {
        'name': 'United States'
      },
      'ca': {
        'name': 'Canada'
      }
    }
  },
  'European Countries': {
    countries: {}
  }
};

const countryComponent = Vue.extend({
  template: '#country-template',
  props: ['country', 'activated'],
  data: () => ({ available: true })
});

const regionComponent = Vue.extend({
  template: '#region-template',
  props: ['region-name', 'region'],
  data: function () {
    const result = {
      countriesActivated: {}
    };

    for (const c of Object.keys(this.region.countries)) {
      result.countriesActivated[c] = { activated: true };
    }
    return result;
  },
  components: {
    'country-c': countryComponent
  },
  computed: {
    activated: {
      get: function() {
        let trueCount = 0;
        let falseCount = 0;
        for (const cName of Object.keys(this.countriesActivated)) {
          if (this.countriesActivated[cName]) {
            ++trueCount;
          } else {
            ++falseCount;
          }
        }
        if (trueCount === 0) {
          return false;
        }
        if (falseCount === 0) {
          return true;
        }
        return 'mixed';
      },
      set: function(newValue) {
        for (const cName of Object.keys(this.countriesActivated)) {
          this.countriesActivated[cName] = newValue;
        }
      }
    }
  }
});

new Vue({
  el: 'body',
  data: {
    regions: rawData
  },
  components: {
    'region-c': regionComponent
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<template id="region-template">
  <li>
    <label>{{ regionName }}</label>
    <input v-if="activated !== 'mixed'" type="checkbox" v-model="activated">
    <span v-else>☯</span>

    <ul>
      <country-c v-for="(countryName, country) in region.countries" :country="country" :activated.sync="countriesActivated[countryName]"></country-c>
    </ul>
  </li>
</template>
<template id="country-template">
  <li>
    <label for="country-{{ country.code }}">{{ country.name }}</label>
    <input id="country-{{ country.code }}" type="checkbox" :disabled="!available" v-model="activated">
  </li>
</template>
<ul>
  <region-c v-for="(regionName, region) in regions" :region-name="regionName" :region="region" :countriesActivated=""></region-c>
</ul>