- Jump To … +
  butterfly_example.ts flamechart_sunburst_example.ts legend_example.ts pie_example.ts plot_area_example.ts plot_zoom_example.ts sankey_example.ts scatterplot_example.ts stack_example.ts swimlanes_example.ts sync_example.ts table_searchable_example.ts table_selectable_example.ts table_sortable_example.ts timeline_example.ts worldbank_example.ts

- ¶

  # C3 Searchable Table

  A table of country data that is sortable, paginated, and searchable.

- ¶

  Remember the column to specify sorting by it.

      var gdp_column: c3.Table.Column<CountryData>;

- ¶

  Keep track of the country we searched for

      var match_country: CountryData;

- ¶

  ## Create the Data Table

- ¶

  Create a `c3.Table` object and set its options. Bind to an anchor DOM element using a string selector.

      var country_table: c3.Table<CountryData> = new c3.Table<CountryData>({
          anchor: '#country_table_example',

- ¶

  Enable the user to sort this table.

          sortable: true,

- ¶

  Limit the table to only show pages of 4 at a time, and enable pagination to change pages.

          limit_rows: 10,
          pagination: true,

- ¶

  Make the table searchable

          searchable: true,

- ¶

  Create an array of column objects to describe the table columns.

          columns: [
              {
                  header: { text: "Country" },
                  cells: { html: (country) => '<b>' + country.name + '</b>' },
              }, {

- ¶

  These columns use custom formatters to set the html content of the cell adding commas, units, rounding, etc. You can add raw HTML if you like. These column also use the `vis` visualization support to render a bar graph based on the cell value.

                  header: { text: "Population" },
                  cells: { text: (country) => d3.format(',')(country.population) },
                  sort: (country) => country.population,
                  vis: 'bar',
              }, {
                  header: { text: "Urbanization" },
                  cells: { text: (country) => country.urban_population.toFixed(1)+'%' },
                  sort: (country) => country.urban_population,
                  vis: 'bar',
                  total_value: 100,
              }, {
                  header: { text: "Land Area" },
                  cells: { html: (country) => (d3.format(',')(Math.round(country.land_area))) + "km<sup>2</sup>" },
                  sort: (country) => Math.round(country.land_area),
                  vis: 'bar',
              },

- ¶

  Assign this column to a variable `gdp_column` so we can refer to it below for setting the default sort.

              gdp_column = {
                  header: { text: "GDP" },
                  cells: { text: (country) => "$" + (d3.format(',')(Math.round(country.gdp))) + "m" },
                  sort: (country) => Math.round(country.gdp),
                  vis: 'bar',
              }, {

- ¶

  By default, the `bar` visualization will base the bar width as a percentage of the total value of all cells. This isn’t always appropriate, though, such as in the case of GDP per capita. So, here we manually set the `total_value` to be the maximum per capita value. Look out for Monaco!

                  header: { text: "GDP per capita" },
                  cells: { html: (country) => "$" + (d3.format(',')(Math.round(country.gdp_per_capita))) },
                  sort: (country) => Math.round(country.gdp_per_capita),
                  vis: 'bar',
                  total_value: function () { return d3.max(country_table.data, (country) => country.gdp_per_capita); },
              },
          ],

- ¶

  Configure the initial column to sort the data on based on the column varible `x_column` we created above.

          sort_column: gdp_column,

- ¶

  Style the row with class `match` if the country matches the one found in the search. `match_country` is set in the match handler below.

          row_options: {
              classes: {
                  'match': (country)=> country === match_country,
              },
          },

- ¶

  Add an event handler to highlight which row was found in a search

          handlers: {
              match: function(search, found_country, i) {
                  match_country = found_country;
                  this.redraw();
              },
          },
      });

- ¶

  ## Modify Table Options

- ¶

  Limit the number of rows

      document.querySelector('#limit_rows').addEventListener('change', function () {
          country_table.limit_rows = this.checked ?
              +(<HTMLInputElement>document.querySelector('#number_of_rows')).value : undefined;
          country_table.redraw();
      });
      document.querySelector('#number_of_rows').addEventListener('change', function () {
          country_table.limit_rows = (<HTMLInputElement>document.querySelector('#limit_rows')).checked ?
              +this.value : undefined;
          country_table.redraw();
      });

- ¶

  Enable pagination to select a different page

      document.querySelector('#pagination').addEventListener('change', function () {
          country_table.pagination = this.checked;
          country_table.redraw();
      });

- ¶

  Set how many pages are shown in the paginator

      document.querySelector('#number_of_pages').addEventListener('change', function () {
          country_table.max_pages_in_paginator = +this.value;
          country_table.redraw();
      });

- ¶

  Allow table to be searchable if table isn’t paginated

      document.querySelector('#searchable_if_not_paginated').addEventListener('change', function () {
          country_table.searchable_if_not_paginated = this.checked;
          country_table.redraw();
      });

- ¶

  ## Load the Country Data

- ¶

  The interface is just a type definition for TypeScript. Ignore this for JavaScript.

      interface CountryData {
          name: string;
          code: string;
          population: number;
          urban_population: number;
          gdp: number;
          gdp_per_capita: number;
          land_area: number;
      }

- ¶

  Load the country CSV data using D3. This loads and merges the data from multiple tables. The data is loaded this way to work with the file format as provided by the World Bank data source.

      d3.csv('data/countries.csv')
          .row((row) => ({
              name: row['name'],
              code: row['world_bank_code'],
          })).get((error, countries:CountryData[]) => {
              var country_lookup = {};
              countries.filter((row) => !!row.code).forEach((row) => {
                  country_lookup[row.code] = row;
              });

- ¶

  Load the country data statistics for the year 2000 from the World Bank data format.

              d3.csv('data/gdp.csv')
                  .row((row) => ({
                      country_name: row['Country Name'],
                      country_code: row['Country Code'],
                      indicator: row['Indicator Code'],
                      value: +row['Value'],
                      year: +row['Year'],
                  })).get((error, rows) => {
                      var indicator_mapping = {
                          'SP.POP.TOTL': 'population',
                          'EN.URB.MCTY.TL.ZS': 'urban_population',
                          'AG.LND.TOTL.K2': 'land_area',
                          'NY.GDP.MKTP.CD': 'gdp',
                          'NY.GDP.PCAP.CD': 'gdp_per_capita',
                      };
                      for (let row of rows) {
                          if (!row.country_code) continue;
                          if (row.year !== 2000) continue;
                          if (!(row.indicator in indicator_mapping)) continue;

- ¶

  Convert GDP to millions of dollars

                          if (indicator_mapping[row.indicator] === 'gdp') row.value /= 1000000;
                          country_lookup[row.country_code][indicator_mapping[row.indicator]] = row.value;
                      }

- ¶

  Setup the table the data and render!

                      d3.selectAll('#loading').remove();
                      country_table.data = countries.filter((country) => country.gdp > 0.000000001);
                      country_table.render();
                  });
          });