2016-09-15 55 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>