2016-09-15 92 views
0

我需要一点帮助。我有世界各地区列表里面国家:Vuejs复选框不确定状态

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

HTML:

  <ul v-for="(regionName, region) in regions"> 

       <li> 
        <label>{{ regionName }}</label> 
        <input type="checkbox" @change="toggleGroupActivation(regionName)"> 
       </li> 

       <li v-for="country in region.countries"> 
        <div> 
         <label for="country-{{ country.code }}">{{ country.name }}</label> 
         <input id="country-{{ country.code }}" type="checkbox" :disabled="!country.available" v-model="country.activated" @change="toggleCountryActivation(regionName, country)"> 
        </div> 
       </li> 
      </ul> 

我尝试建立与复选框,在这里你可以选择的国家名单。如果选中整个区域的复选框,则会自动检查该区域中的所有国家/地区。如果只检查区域中的几个国家(不是全部),则需要显示按地区复选框的不确定状态复选框。如何处理它?

+0

使用jQuery,找到所需的复选框元素在DOM,并与.props()添加不确定的状态。这是肮脏的方式。寻找更优雅(vuejs)的方式 – Julius

+0

你能否提供显示每个状态中复选框的指定方式的HTML? –

+0

更新有问题的详细信息 – Julius

回答

0

“全选”复选框的常用解决方案是使用computed with a setter。当选中该框时,将检查所有子框(通过设置功能)。当一个子框改变时,Select All框值被重新评估(在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>