How to remove additional prompt option “Select all” from dc.js selectMenu? [duplicate]

亡梦爱人 提交于 2020-01-24 19:32:05

问题


I have a dimension with the values A,B,C,D.

I would like to create a selectMenu with dc.js, where

  • the value A is selected by default

  • only one value can be selected (no mulit-selection)

  • always one value has to be selected

a) I used .multiple(false) and expected that a single value is selected by default. However, the default state of the menu is to select all available options (=no filtering).

b) I also tried to set the promptTitle and promptValue to my wanted initial value A. Also see doc at https://dc-js.github.io/dc.js/docs/html/SelectMenu.html

However, then the option A is displayed twice (and applying the initial value does not work either):

let typeSelection = dc.selectMenu('#type'); 

typeSelection.dimension(typeDim)                         
             .multiple(false)
             .group(typeGroupCount)
             .title(d => d.key)
             .promptText('A')
             .promptValue('A')
             .controlsUseVisibility(true);

c) I also tried to use the method filterDisplayed. However, only the single options are passed as arguments and there does not seem to be a way to disable the 'Select all' option here.


回答1:


A. Here is a manual implementation of a single selection combo box:

<div>
    <label>Type</label>
    <select id='type' style='padding:5px;'>
        <option>A</option>
        <option>B</option>
        <option>C</option>
        <option>D</option>
    </select>
</div>

-

dc.renderAll();

d3.select('#type')
  .on('change', applyTypeSelection);

applyTypeSelection();

function applyTypeSelection(){
    let selectedType = d3.select('#type').node().value;
    typeDim.filter(type => {
      return type === selectedType;
    });
    dc.redrawAll();                
}

B. Here is a full example for another approach. It is based on the pretransition event that is used in the answer of the old duplicate question

Change text and remove Select All from dc.selectMenu

dc.selectMenu('#type') 
  .dimension(typeDim)                         
  .multiple(false)
  .group(typeGroupCount)
  .title(d => d.key)
  .on('pretransition', event => {
        typeSelection.select('option[value=""]')
   .remove();
   })
   .filter('A');

<html>

	<head>

		<title>dc demo</title>

		<meta http-equiv='content-type' content='text/html; charset=UTF8'>

		<!-- this demo is based on following tuturials:
		   https://www.tutorialspoint.com/dcjs/dcjs_introduction_to_d3js.htm 
		   https://www.codeproject.com/articles/693841/making-dashboards-with-dc-js-part-1-using-crossfil		
	    -->

	     



		 <script src='https://d3js.org/d3.v4.min.js'></script>
		 <script src='https://cdnjs.cloudflare.com/ajax/libs/crossfilter2/1.5.2/crossfilter.min.js'></script>
		 <script src='https://cdnjs.cloudflare.com/ajax/libs/dc/3.1.8/dc.min.js'></script>
		 <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/dc/3.1.8/dc.css" />

	</head>
	
	<body>
	    
	    <div style="font-family:arial;">

			 <div style="float:left;padding:10px;">
				<div >
					<label>Number of colors:</label>
					<div id='color-chart-count'></div>
				</div>

				<div>
					<label>Value sum for colors:</label>
					<div id='color-chart-value-sum'></div>
				</div>
			</div>

			<div style="float:left;padding:10px;">
				<div>
					<label>Number of ages:</label>
					<div id='age-chart-count'></div>
				</div>

				<div>
					<label>Value sum for ages:</label>
					<div id='age-chart-value-sum'></div>
				</div>
			</div>

			<div style="float:left;padding:10px;">
				<div>
					<label>Type</label>
					<div id="type"></div>
					<!--
					<select id='type' style='padding:5px;'>
					    <option>A</option>
					    <option>B</option>
					    <option>C</option>
					    <option>D</option>
					</select>
					-->
				</div>
			</div>

	    </div>
	    
	    
        <div style="font-family:arial; float:left">
            <label for='value-chart'>Values:</label>
	        <div id='value-chart'></div>
        </div>
	    
	
		<script>
			
			let data = [			              

						  {color: 'red', age: 1, type: 'A', value: 10},
						  {color: 'red', age: 1, type: 'B', value: 11},
						  {color: 'red', age: 1, type: 'C', value: 12},
						  {color: 'red', age: 1, type: 'D', value: 13},	

						  {color: 'red', age: 2, type: 'A', value: 20},
						  {color: 'red', age: 2, type: 'B', value: 21},
						  {color: 'red', age: 2, type: 'C', value: 22},
						  {color: 'red', age: 2, type: 'D', value: 23},

						  {color: 'red', age: 3, type: 'A', value: 30},
						  {color: 'red', age: 3, type: 'B', value: 31},	
						  {color: 'red', age: 3, type: 'C', value: 32},
						  {color: 'red', age: 3, type: 'D', value: 33},
						  		  

						  {color: 'green', age: 1, type: 'A', value: 100},
						  {color: 'green', age: 1, type: 'B', value: 105},
						  {color: 'green', age: 1, type: 'C', value: 110},
						  {color: 'green', age: 1, type: 'D', value: 115},						  

						  {color: 'green', age: 2, type: 'A', value: 120},
						  {color: 'green', age: 2, type: 'B', value: 125},
						  {color: 'green', age: 2, type: 'C', value: 130},
						  {color: 'green', age: 2, type: 'D', value: 135},						  

						  {color: 'green', age: 3, type: 'A', value: 140},
						  {color: 'green', age: 3, type: 'B', value: 145},
						  {color: 'green', age: 3, type: 'C', value: 150},
						  {color: 'green', age: 3, type: 'D', value: 155},


						  {color: 'blue', age: 1, type: 'A', value: 300},
						  {color: 'blue', age: 1, type: 'B', value: 305},
						  {color: 'blue', age: 1, type: 'C', value: 310},
						  {color: 'blue', age: 1, type: 'D', value: 315},

						  {color: 'blue', age: 2, type: 'A', value: 320},
						  {color: 'blue', age: 2, type: 'B', value: 325},
						  {color: 'blue', age: 2, type: 'C', value: 330},
						  {color: 'blue', age: 2, type: 'D', value: 335},

						  {color: 'blue', age: 3, type: 'A', value: 340},
						  {color: 'blue', age: 3, type: 'B', value: 345},
						  {color: 'blue', age: 3, type: 'C', value: 350},
						  {color: 'blue', age: 3, type: 'D', value: 355},
						];

            //create instance of cross filter
			let cf = crossfilter(data);			 

            //define dimensions and groups
            let colorDim = cf.dimension(d=> d.color);
            let colorGroupCount = colorDim.group().reduceCount();
            let colorGroupValueSum = colorDim.group().reduceSum(d => d.value);

            let ageDim = cf.dimension(d=> d.age);
            let ageGroupCount = ageDim.group().reduceCount();
            let ageGroupValueSum = ageDim.group().reduceSum(d => d.value);

            let typeDim = cf.dimension(d=> d.type);
            let typeGroupCount = typeDim.group().reduceCount();
            let typeGroupValueSum = typeDim.group().reduceSum(d => d.value);

            let colorAgeDim = cf.dimension(d => [d.color, d.age]);


            function reduceAdd(previous, current) {

            	if(current){
            		if(current.value !== null){
            			if(previous.sum === null){
            				previous.sum = current.value;
            				previous.count = 1;
            			} else {
            				previous.sum += current.value;
            				previous.count += 1;

            			}
            		} 
            	} 
            	return previous;            									
			}

			function reduceRemove(previous, current) {					
				if(current){
            		if(current.value !== null){
            			if(previous.sum !== null){
            				previous.sum -= current.value;
            				previous.count -= 1;
            				if(previous.count === 0){
            					previous.sum = null;
            				}
            			} 
            		} 
            	} 
            	return previous; 				
			}

			function reduceInit(previous) {
					return { 
					        sum: null,
					        count: 0
					       };
			}
				              
            let colorAgeGroup = colorAgeDim.group()
                                        .reduce(reduceAdd, reduceRemove, reduceInit);

            let filteredColorAgeGroup = removeMissingEntries(colorAgeGroup);

            function removeMissingEntries(sourceGroup) {
				return {
					all:function () {
						return sourceGroup.all().filter(function(d) {							
							return d.value.sum !== null; 
						});
					}
				};
			}

            let ordinalColors =  ['red','green','blue'];    
            let ordinalAgeColors =  ['lightgray','grey','#666666']; 
            let ordinalTypeColors =   ['#ffff0020','#ffff0050','#ffff0090', '#ffff00'];                  

            //color charts

            let rgbColorScale = d3.scaleOrdinal().domain(ordinalColors).range(ordinalColors);

            let colorChartCount = barChart('#color-chart-count')               
				.xAxisLabel('Color')  				   				
				.x(d3.scaleBand().domain(ordinalColors))		
				.dimension(colorDim)		
				.yAxisLabel('Count')					
				.group(colorGroupCount)							
				.defineColors(rgbColorScale);				

			colorChartCount.yAxis().ticks(4);		
				

			barChart('#color-chart-value-sum')               
				.xAxisLabel('Color')  				         				
				.x(d3.scaleBand().domain(ordinalColors))		
				.dimension(colorDim)		
				.yAxisLabel('Value sum')				
				.group(colorGroupValueSum)
				.defineColors(rgbColorScale);				

            //age charts

            let ageColorScale = d3.scaleOrdinal().domain([1,2,3]).range(ordinalAgeColors);

          

			let ageChartCount = barChart('#age-chart-count')              
				.xAxisLabel('Age') 				           				
				.x(d3.scaleLinear().domain([1,2,3]))		
				.dimension(ageDim)		
				.yAxisLabel('Count')				
				.group(ageGroupCount)			
				.defineColors(ageColorScale);

			ageChartCount.yAxis().ticks(4);	

			barChart('#age-chart-value-sum')               
				.xAxisLabel('Age')  				   				
				.x(d3.scaleLinear().domain([1,2,3]))	
				.dimension(colorDim)		
				.yAxisLabel('Value sum')				
				.group(ageGroupValueSum)
				.defineColors(ageColorScale);

            //type selection   
            
            //dc selection menu
            //also see https://dc-js.github.io/dc.js/docs/html/SelectMenu.html#undefined 
            //and https://stackoverflow.com/questions/51746692/change-text-and-remove-select-all-from-dc-selectmenu
              
            dc.selectMenu('#type')
              .dimension(typeDim)                         
              .multiple(false)
              .group(typeGroupCount)
              .title(d => d.key)
              .on('pretransition', event => {
				typeSelection.select('option[value=""]')
			    .remove();
			  })
              .filter('A');

			//helper functions

			function barChart(elementSelector){

				let barChart = dc.barChart(elementSelector)
					.width(200)
					.height(200)				
					.xUnits(dc.units.ordinal)  			
					.margins({top:10,left:40,right:5,bottom:35})	
					.barPadding(0.1)
					.outerPadding(0.1)					
					.transitionDuration(500);

					barChart.defineColors = function(colorScale){
						
						this.renderlet(chart=>{
						    chart.selectAll('rect.bar')
							     .each(function(d){

                                    let isSelected = this.classList.contains('selected');
                                    if(isSelected){
                                        d3.select(this).attr('style', 'fill: ' + colorScale(d.x) + ';stroke-width:2;stroke:#39ff14');
                                       
                                    } else {
                                    	d3.select(this).attr('style', 'fill: ' + colorScale(d.x));
                                    }

								    
							     });
							 	
					    });
					    return this;
					}

					return barChart;
			}	

             
             //value chart
             let chart = dc.seriesChart('#value-chart');

			 chart
				.width(500)
				.height(500)
				.chart( c => 
				       dc.lineChart(c)
				       .renderDataPoints(true)
				           				       
				       	
				)				
				.xAxisLabel('Age')
				.x(d3.scaleLinear().domain([1,3]))
				.dimension(colorAgeDim)				
				.yAxisLabel('Value')
				.elasticY(true)
				.group(filteredColorAgeGroup)					
				.brushOn(false)	
				.clipPadding(10)
				.mouseZoomable(true)
				.seriesAccessor(d => d.key[0])
				.keyAccessor(d => d.key[1])
				.valueAccessor(d => {
					return d.value.sum;
				})
				.ordinalColors(['blue','green','red'])
				.legend(dc.legend().x(430).y(350)); 
			
            
            dc.renderAll();

            

           
                        
            

            //dimensions can also be used for filtering:
            
            //let color_red = colorDim.filter('red');           
            //let filterResult = JSON.stringify(color_red.top(Infinity)).replace('[','[\n\t').replace(/}\,/g,'},\n\t').replace(']','\n]');
            //console.log(filterResult);

            //let functionFilter = ageDim.filter(age => age === 2);  
            //let functionFilterResult = JSON.stringify(functionFilter.top(Infinity)).replace('[','[\n\t').replace(/}\,/g,'},\n\t').replace(']','\n]');
            //console.log(functionFilterResult);


		</script>
	
	
	</body>

</html>


来源:https://stackoverflow.com/questions/59826057/how-to-remove-additional-prompt-option-select-all-from-dc-js-selectmenu

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!