2017-09-03 2 views
2

Je souhaite filtrer les données de la table en fonction de l'âge et de la hauteur en même temps en utilisant 2 curseurs de plage.Comment puis-je utiliser deux curseurs de plage en même temps?

J'ai implémenté 2 curseurs de plage (Âge et Hauteur) en utilisant d3.slider.js et dc.dataTable. Je veux utiliser ces deux curseurs en même temps, mais il semble qu'ils ne fonctionnent pas correctement.

Egalement, sous le tableau, il y a le texte "49 sélectionné parmi 49 enregistrements". Les chiffres ne changent pas lorsque vous utilisez les curseurs.

code:

var dataTable = dc.dataTable("table#list"); 
    var dispatch = d3.dispatch('load','filter'); 

    d3.json('data.json',function(json){ 
     dispatch.load(json) 
    }); 

    dispatch.on('load',function(json) { 
     var formatNumber = d3.format(",d"); 
     var facts = crossfilter(json); 
     var dimensionAge = facts.dimension(function(d) { 
      return +d.age; 
     }); 
     var accessorAge = function(d) { 
      return d.age; 
     }; 
     var dimensionHeight = facts.dimension(function(d) { 
      return +d.height; 
     }); 
     var accessorHeight = function(d) { 
      return d.height; 
     }; 
     var range = d3.extent(json, accessorAge); 
     var range2 = d3.extent(json, accessorHeight); 
     var all = facts.groupAll(); 

     d3.select("div#slider3") 
      .call(d3.slider().axis(true).min(range[0]).max(range[1]).value(range) 
      .on("slide", function(evt,value) { 
       dispatch.filter(value); 
       d3.select("#slider3textmin").text(Math.floor(value[0])); 
       d3.select("#slider3textmax").text(Math.floor(value[1])) 
      })) 

     d3.select("div#slider4") 
      .call(d3.slider().axis(true).min(range2[0]).max(range2[1]).value(range2) 
      .on("slide", function(evt,value) { 
       dispatch.filter(value); 
       d3.select("#slider4textmin").text(Math.floor(value[0])); 
       d3.select("#slider4textmax").text(Math.floor(value[1])) 
      })) 


     FieldNames = [ 
      "", 
      "Age", 
      "Weight", 
      "Height", 
      "Eye Color", 
      "Hair Color", 
      "Race", 
      "Sex", 
      "Annual Income" 
     ]; 

     d3.select("tr#FieldNames").selectAll("th") 
      .data(FieldNames) 
      .enter() 
      .append("th") 
      .append("text") 
      .text(function(d){ 
       return d; 
      }); 

     dataTable 
      .dimension(dimensionAge) 
      .group(function(d) { 
       return d.sex; 
      }) 
      .columns([ 
       function(d) {return "";}, 
       function(d) {return d.age;}, 
       function(d) {return d.weight;}, 
       function(d) {return d.height;}, 
       function(d) {return d.eyeColor;}, 
       function(d) {return d.hairColor;}, 
       function(d) {return d.race;}, 
       function(d) {return d.sex;}, 
       function(d) {return formatNumber(d.annualIncome);} 
      ]); 

     dispatch.on('filter',function(value){ 
      dataTable.replaceFilter(dc.filters.RangedFilter(value[0], value[1])); 
      dataTable.redraw(); 
     }) 

     dc.dataCount(".dc-data-count") 
      .dimension(facts) 
      .group(all); 

     dc.renderAll(); 

    }); 

Link to the website

Plunker

Répondre

2

réponse originale on the dc.js users group.

Belle utilisation de d3.slider.js - Je n'ai pas vu cela utilisé avec dc.js avant. En un coup d'œil, je vois deux problèmes ici. D'abord, vous utilisez une répartition pour les deux curseurs, donc les deux curseurs filtrent l'âge, puisque c'est la dimension de la table. Vous voudrez probablement créer une autre dimension pour le filtrage par hauteur, et vous n'avez pas vraiment besoin de pour l'attacher à un graphique.

En second lieu, au lieu de simplement redessiner le tableau avec dataTable.redraw(), vous voulez probablement appeler dataTable.redrawGroup() de telle sorte que toutes les cartes dans son groupe graphique se redessine, y compris le DataCount.

Plus précisément:

  1. vous aurez besoin de deux événements de filtre dans votre dépêche

    var dispatch = d3.dispatch('load','filterAge','filterHeight'); 
    
  2. le curseur âge appellera filterAge

      dispatch.filterAge(value); 
    

    et le curseur de la hauteur appellera filterHeight

      dispatch.filterHeight(value); 
    
  3. le gestionnaire d'événements filter actuel va maintenant gérer filterAge et il appellera redrawGroup

    dispatch.on('filterAge',function(value){ 
         dataTable.replaceFilter(dc.filters.RangedFilter(value[0], value[1])); 
         dataTable.redrawGroup(); 
        }) 
    
  4. nous ajoutons un autre gestionnaire filterHeight qui filtre directement dimensionHeight et redessine aussi le groupe graphique

    dispatch.on('filterHeight',function(value){ 
         dimensionHeight.filter([value[0], value[1]]); 
         dataTable.redrawGroup(); 
        }) 
    
  5. Tout réinitialiser devra également effacer dimensionHeight. (Puisque cette dimension n'est utilisée par aucun graphique, dc.filterAll() ne le trouvera pas.)

     <a href="javascript: dimensionHeight.filter(null); dc.filterAll(); dc.renderAll();">Reset All</a> 
    

Fork of your plunker.

+0

Pourriez-vous aussi, pl facilité, résoudre le problème avec le texte "49 sélectionnés sur 49 dossiers" sous le tableau? Lorsque j'utilise le curseur Age, les chiffres ne changent pas du tout. Et aussi le lien "Reset All" ne fonctionne pas correctement. –

+0

Impossible d'enregistrer la modification 'redrawGroup' pour' filterAge' car je ne suis pas habitué à Plunker. Corrigé cela, et ajouté ** Réinitialiser tout ** à ma réponse. – Gordon

+0

@Gordon je veux modifier votre réponse, mais je ne savais pas comment modifier plunker, désolé .. – KEKUATAN

0

cela pour INITIAL, les 49 sélectionnés sur 49 dossiers modifier déjà correcly

remplacer

<a href="javascript: dimensionHeight.filter(null); dc.filterAll(); dc.renderAll();">Reset All</a> 

à cette

<a href="#" onclick="sololo()">Reset All</a> 

ajouter cette après l'envoi de la charge

dispatch.on('load',function(json) { 
//your code 
})  

function sololo(){ 
        //table 
       dispatch.filterAge([0,100]); 
       dispatch.filterHeight([0,100]); 
       //text slider 
       d3.select("#slider4textmin").text(0) 
        d3.select("#slider4textmax").text(0) 
        d3.select("#slider3textmin").text(0); 
        d3.select("#slider3textmax").text(0) 
        //slider 
        d3.select('#slider3').select('#handle-one').style('left','0%') 
       d3.select('#slider3').select('#handle-two') .style('right','0%') 
       d3.select('#slider3').select('div').style('left','0%').style('right','0%') 
        d3.select('#slider4').select('#handle-one').style('left','0%') 
       d3.select('#slider4').select('#handle-two') .style('right','0%') 
       d3.select('#slider4').select('div').style('left','0%').style('right','0%') 
    } 
+0

Bon point sur la réinitialisation des curseurs. Oof, est-ce la seule façon de le faire? – Gordon

+0

mmmm .... vous ne dessinez pas le curseur manuellement en utilisant liblary, donc la meilleure chose est d'injecter sur l'élément html, vous pouvez utiliser la boucle, vous pouvez retirer ce curseur et le dessiner à nouveau, ou en utilisant la fonction d'accumulation sur ce curseur. js pour faire cela s'il y en a un – KEKUATAN

+0

J'ai un peu piqué dans d3.slider.js et en effet il semble qu'il n'y ait pas de bonne API pour cela - cela permet de mettre à jour la valeur mais il s'attend à ce que la valeur soit scalaire, et tombe en panne passer un tableau pour les mises à jour. Donc je pense que c'est la meilleure solution pour les curseurs pour l'instant. Une partie semble manquer - cela ne réinitialise pas le bon curseur, juste le fond bleu. – Gordon