Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BubbleSeries not working #10

Closed
sweetyv opened this issue Aug 13, 2017 · 21 comments
Closed

BubbleSeries not working #10

sweetyv opened this issue Aug 13, 2017 · 21 comments

Comments

@sweetyv
Copy link

sweetyv commented Aug 13, 2017

Hi @whawker ,

I am working with Bubble series and its not generating the chart. If I change the series type to any other type(E.g. Scatter), it works fine. I am not sure if I am passing the data correctly or its some other issue. Please help.

This is the below code:

import React, { Component } from 'react';
import {
  HighchartsChart, Chart, XAxis, YAxis,  Tooltip, Legend, BubbleSeries, ScatterSeries
} from 'react-jsx-highcharts';

class CompetitiveLandscape extends Component {
  render() {
    const plotOptions = {
    };
    const data = [
       [154, 97, 100]
     ];

    return (
      <div className="chartApp">
        <HighchartsChart plotOptions={plotOptions}>
          <Chart zoomType="xy"  />
          <XAxis name="Month">
            <XAxis.Title>Year-Month</XAxis.Title>
          </XAxis>
          <YAxis id="number">
            <YAxis.Title>Basic VS. Premium</YAxis.Title>
            <BubbleSeries id="Premium" name="Premium" color="#e96c39" data={data} />
          </YAxis>
          <Legend />
          <Tooltip backgroundColor="white" shadow={false}></Tooltip>
        </HighchartsChart>
      </div>
    );
  }
}

export default CompetitiveLandscape;
@whawker
Copy link
Owner

whawker commented Aug 13, 2017

Bubble series require the highcharts-more extension (see here to see what else "more" provides)

You should be able to include it by

import Highcharts from 'highcharts';
require('highcharts/highcharts-more')(Highcharts);

@sweetyv
Copy link
Author

sweetyv commented Aug 13, 2017

Awesome! Its working. Thank you so much for the quick help :)

@sweetyv sweetyv closed this as completed Aug 13, 2017
@sweetyv
Copy link
Author

sweetyv commented Aug 16, 2017

Hi @whawker,

The bubble series is working fine but I want to create a dynamic bubble series. For e.g I want multiple bubbles but I am not sure how many bubbles will be created. That will depend on my selection of filters.
Is there a way we can create multiple/dyanmic bubble series with some loop or something depending on the JSON data passed to my chart?

Please help.

@whawker
Copy link
Owner

whawker commented Aug 16, 2017

Do you mean an unknown number of Bubbles in a single series? Or multiple Bubble series?

The add/remove example demonstrates how you could have an arbitrary number of series, if that helps?

@sweetyv
Copy link
Author

sweetyv commented Aug 16, 2017

Unknown number of multiple Bubble series.

@whawker Below is the example of AreaSpline Series. In this as well, I want to create multiple Areaspline series depending on the JSON file which has number of categories(Skincare,Haircare etc).

I think I am making mistake in loop. Please help.


import React, { Component } from 'react';
import {
 HighchartsChart, Chart, XAxis, YAxis,  Tooltip, AreaSplineSeries
} from 'react-jsx-highcharts';
import axios from 'axios';
import Dropdown from './dropdowns';

class SearchVolumeTrends extends Component {
 constructor(props) {
   super(props);
   this.state = {
     data: []
   };
 }

 componentDidMount() {
   axios.post('some url', {
     categories: 'Skincare - pharma',
     sub_categories: 'Generic - Ingredients',
     benefit: 'Anti-Aging',
     behaviour: 'Informational - Generic',
     brand_type: 'Non Brand'
   })
   .then(response => {
     this.setState({
       data: response.data.data
     });
   })
   .catch(error => {
     console.log('Error fetching and parsing data', error);
   });
 }

 renderSVTValue() {
   return this.state.data.map(data => (
     <AreaSplineSeries id="Volume" name="Volume" color="#2fd0b5" data={data.svt} />
   ));
 }

 render() {
   const plotOptions = {
     series: {
       fillOpacity: 0.5,
       marker:{
         enabled: false
       }
     }
   };

   return (
     <div className="chartApp">
       <HighchartsChart plotOptions={plotOptions} >
         <Chart />
         <XAxis name="Month" gridLineWidth="1" gridLineDashStyle="ShortDash">
           <XAxis.Title>Year-Month</XAxis.Title>
         </XAxis>
         <YAxis id="number" gridLineWidth="0" startOnTick="false">
           <YAxis.Title>Search Volume</YAxis.Title>
           {this.renderSVTValue()}
         </YAxis>
         <Tooltip shared backgroundColor="white" shadow={false}></Tooltip>
       </HighchartsChart>
     </div>
   );
 }
}

export default SearchVolumeTrends;

@whawker
Copy link
Owner

whawker commented Aug 16, 2017

It's hard to say exactly, because I don't know the shape of the JSON being returned. But there are a few issues here,

Firstly renderSVTValue should be bound to this in you constructor function. example

Secondly renderSVTValue is returning an array, which I don't think will work in React v15, you need to do the loop in the render function, and have renderSVTValue return a single component.

Lastly in the code you posted above, every AreaSplineSeries is rendered with the same id prop, but React JSX Highcharts needs each series to have a unique ID.

This probably wont work perfectly, because I'm guessing at the shape of your JSON data. But something along the lines of...

renderSVTValue ({ somePropertyUniqueToTheSeries, svt }) {
  return (
    <AreaSplineSeries id={somePropertyUniqueToTheSeries} name="Volume" color="#2fd0b5" data={svt} key={somePropertyUniqueToTheSeries} />
  );
}

render () {
  return (
    <HighchartsChart plotOptions={plotOptions}>
      // redacted
      {this.state.data.map(this.renderSVTValue)}
      // redacted
    </HighchartsChart>
  );
}

@sweetyv sweetyv reopened this Aug 16, 2017
@sweetyv
Copy link
Author

sweetyv commented Aug 16, 2017

Ohk great. Thanks, that makes sense.
Just sending you the JSON file incase you can tell me if I am doing anything wrong.

@sweetyv
Copy link
Author

sweetyv commented Aug 16, 2017

JSON DATA:

{
"data": {
"svt": [{
"id": 0,
"name": "Face Cream",
"value": [216300, 319270, 377930, 345060, 389510, 351560, 366510, 358180, 345020, 342740, 302060, 246690],
"date": ["2017-7", "2017-6", "2017-5", "2017-4", "2017-3", "2017-2", "2017-1", "2016-12", "2016-11", "2016-10", "2016-9", "2016-8"]
}, {
"id": 1,
"name": "Generic",
"value": [146660, 177460, 217190, 226920, 225800, 177670, 211120, 200140, 198080, 182360, 183560, 157610],
"date": ["2016-7", "2016-6", "2016-5", "2016-4", "2016-3", "2016-2", "2016-1", "2015-12", "2015-11", "2015-10", "2015-9", "2015-8"]
}, {
"id": 2,
"name": "Generic - Ingredients",
"value": [127300, 154480, 164590, 150640, 186970, 160870, 165900, 135510, 151030, 148480, 152260, 126560],
"date": ["2015-7", "2015-6", "2015-5", "2015-4", "2015-3", "2015-2", "2015-1", "2014-12", "2014-11", "2014-10", "2014-9", "2014-8"]
}, {
"id": 3,
"name": "Mask",
"value": [28680, 30510, 35300, 41490, 49220, 48740, 51610, 43520, 50960, 47730, 38450, 30030],
"date": ["2014-7", "2014-6", "2014-5", "2014-4", "2014-3", "2014-2", "2014-1", "2013-12", "2013-11", "2013-10", "2013-9", "2013-8"]
}, {
"id": 4,
"name": "Body Cream",
"value": [52370, 66540, 51300, 35880, 30490, 19340, 21140, 17700, 14780, 13850, 18280, 31070],
"date": ["2013-7", "2013-6", "2013-5", "2013-4", "2013-3", "2013-2", "2013-1", "2012-12", "2012-11", "2012-10", "2012-9", "2012-8"]
}, {
"id": 5,
"name": "Cream",
"value": [32630, 45200, 33930, 20550, 18500, 12880, 12780, 12160, 11950, 11630, 11210, 18080],
"date": ["2012-7", "2012-6", "2012-5", "2012-4", "2012-3", "2012-2", "2012-1", "2011-12", "2011-11", "2011-10", "2011-9", "2011-8"]
}, {
"id": 6,
"name": "Eye Cream",
"value": [9580, 11520, 18220, 20490, 25990, 23910, 28140, 21930, 20440, 19020, 14260, 11300],
"date": ["2011-7", "2011-6", "2011-5", "2011-4", "2011-3", "2011-2", "2011-1", "2010-12", "2010-11", "2010-10", "2010-9", "2010-8"]
}, {
"id": 7,
"name": "Serum",
"value": [13630, 12520, 15150, 16740, 20600, 18400, 18720, 16050, 17130, 16700, 15420, 14400],
"date": ["2010-7", "2010-6", "2010-5", "2010-4", "2010-3", "2010-2", "2010-1", "2009-12", "2009-11", "2009-10", "2009-9", "2009-8"]
}, {
"id": 8,
"name": "Cream - Ingredients",
"value": [15400, 15200, 20160, 18410, 20350, 15200, 19000, 15110, 13900, 14370, 14810, 14460],
"date": ["2009-7", "2009-6", "2009-5", "2009-4", "2009-3", "2009-2", "2009-1", "2008-12", "2008-11", "2008-10", "2008-9", "2008-8"]
}, {
"id": 9,
"name": "Body Scrub",
"value": [20860, 20960, 20640, 15410, 15290, 11890, 12460, 12450, 12590, 10870, 15140, 17070],
"date": ["2008-7", "2008-6", "2008-5", "2008-4", "2008-3", "2008-2", "2008-1", "2007-12", "2007-11", "2007-10", "2007-9", "2007-8"]
}]
},
"status": "OK",
"msg": "No error"
}

@whawker
Copy link
Owner

whawker commented Aug 16, 2017

Ok you can either assume the date values, and add them as an XAxis category

<XAxis categories={["2008-7", "2008-6", "2008-5", "2008-4", "2008-3", "2008-2", "2008-1", "2007-12", "2007-11", "2007-10", "2007-9", "2007-8"]} />

Or use something like lodash.zip to combine the date and value arrays into a multidimensional array.

import zip from 'lodash/zip';

renderSVTValue ({ id, name, date, value }) {
  const strId = `series-${id}`;
  const data = zip(date, value); // Using lodash zip to create multidimensional array
  return (
    <AreaSplineSeries id={strId} name={name} color="#2fd0b5" data={data} key={strId} />
  );
}

render () {
  const data = this.state.data;
  if (data.hasOwnProperty('svt') === false) return null; // Wait till data is fetched before rendering

  return (
    <HighchartsChart plotOptions={plotOptions}>
      // redacted
      {data.svt.map(this.renderSVTValue)}
      // redacted
    </HighchartsChart>
  );
}

@whawker
Copy link
Owner

whawker commented Aug 16, 2017

Also, closing this as there is not actually an issue to be fixed here.

@whawker whawker closed this as completed Aug 16, 2017
@sweetyv
Copy link
Author

sweetyv commented Aug 16, 2017

Amazing. Thank you very much @whawker. It worked. Appreciate it 👍

@sweetyv
Copy link
Author

sweetyv commented Aug 16, 2017

Hi @whawker,

One more query. Sorry.
So I want my categories(date) also for X axis from JSON file. I tried following code referring your code. But i am not sure how to add it is a category attribute.

renderTrendingDate({ date }) {
   return(
     <XAxis categories={date}></XAxis>
   );
 }
render() {
   const trendingDate = this.state.data;
   if (trendingDate.hasOwnProperty('svt') === false) return null; // Wait till data is fetched before rendering



   return (
     <div className="chartApp">
       <HighchartsChart plotOptions={plotOptions}>
         <Chart />
         <XAxis categories={trendingDate.svt.map(this.renderTrendingDate)}>
           <XAxis.Title>Year-Month</XAxis.Title>
         </XAxis>
         <YAxis id="number">
           <YAxis.Title>Trend Production</YAxis.Title>
           {data.svt.map(this.renderTrendingValue)}
         </YAxis>
       </HighchartsChart>
     </div>
   );
 }

@whawker
Copy link
Owner

whawker commented Aug 16, 2017

You don't need to render any additional XAxis components for the categories attribute, it just expects an array as a prop value.

Something like:

import uniq from 'lodash/uniq';

getDateCategories (svtData) {
  const allDates = svtData.reduce((dates, svt) => {
    return dates.concat(svt.date); // Combine all svt.date arrays into single array
  }, []);

  return uniq(allDates.sort()); // Sort combined dates and remove duplicates.
}

render() {
   const trendingDate = this.state.data;
   if (trendingDate.hasOwnProperty('svt') === false) return null; // Wait till data is fetched before rendering

   const categories = this.getDateCategories(trendingData.svt);

   return (
     <div className="chartApp">
       <HighchartsChart plotOptions={plotOptions}>
         <Chart />
         <XAxis type="category" categories={categories}>
           <XAxis.Title>Year-Month</XAxis.Title>
         </XAxis>
         <YAxis id="number">
           <YAxis.Title>Trend Production</YAxis.Title>
           {data.svt.map(this.renderTrendingValue)}
         </YAxis>
       </HighchartsChart>
     </div>
   );
 }

@sweetyv
Copy link
Author

sweetyv commented Aug 16, 2017

Can't thank you enough. I tried to make component with XAxis and that worked too. But your way is just perfect. 👍

@sweetyv
Copy link
Author

sweetyv commented Aug 16, 2017

Hi @whawker, just wanted to ask you what if I have categories(names) in XAxis and not dates. The JSON looks like below:

{"data":{"svt":[{"id":0,"name":"Purchase","value":5810110,"date":"2016-8"},{"id":1,"name":"Informational - Generic","value":2722980,"date":"2016-8"},{"id":2,"name":"Consideration - Product","value":1108180,"date":"2016-8"},{"id":3,"name":"Informational - Product","value":917530,"date":"2016-8"},{"id":4,"name":"Consideration - How to","value":172570,"date":"2016-8"},{"id":5,"name":"Consideration - Price","value":170840,"date":"2016-8"},{"id":6,"name":"Consideration - Generic","value":137800,"date":"2016-8"},{"id":7,"name":"Informational - How to","value":69230,"date":"2016-8"}]},"status":"OK","msg":"No error"}

This is the below code you had shared earlier. I tried to tweak it as per the requirement but not sure how to loop inside attribute.

getDateCategories (behName) {
   const allNames = behName.reduce((name, svt) => {
     return name.concat(svt.name); // Combine all svt.date arrays into single array
   }, []);

   // return uniq(allNames.sort()); // Sort combined name and remove duplicates.
 }
render() {
   const behaviour = this.state.data;
   if (behaviour.hasOwnProperty('svt') === false) return null; // Wait till data is fetched before rendering

   const categories = this.getDateCategories(behaviour.svt);


   return (
     <div className="chartApp">
       <HighchartsChart plotOptions={plotOptions}>
         <Chart />
         <XAxis name="Month" type="category" categories={categories}>
           <XAxis.Title>Year-Month</XAxis.Title>
         </XAxis>
         <YAxis id="number">
           <YAxis.Title>Top 10 Behaviors</YAxis.Title>
           {data.svt.map(this.renderBehValue)}
         </YAxis>

         <Tooltip shared backgroundColor="white" shadow={false}></Tooltip>
       </HighchartsChart>
     </div>
   );
 }

Could you please help?

@whawker
Copy link
Owner

whawker commented Aug 16, 2017

The line // return uniq(allNames.sort()); // Sort combined name and remove duplicates. is commented out?

@sweetyv
Copy link
Author

sweetyv commented Aug 16, 2017

Yes, I had commented it for this example(which doesnt have date on xAxis and has categories instead) considering i don't need any sorting or unique values.

@whawker
Copy link
Owner

whawker commented Aug 16, 2017

Yes, but you still need to return something from the function...

 getDateCategories (behName) {
   const allNames = behName.reduce((name, svt) => {
     return name.concat(svt.name); // Combine all svt.date arrays into single array
   }, []);

   return allNames; // Otherwise the function returns undefined
 }

@sweetyv
Copy link
Author

sweetyv commented Aug 16, 2017

This is showing me only one category i.e the first category "Purchase" from my JSON. How do I make a loop or show all the categories on XAxis?

@sweetyv
Copy link
Author

sweetyv commented Aug 16, 2017

Just for your reference.
2

@sweetyv
Copy link
Author

sweetyv commented Aug 18, 2017

Hi @whawker,

Could you please help me with the above issue? I tried working around the code and removed the below code as I don't need any sorting or reducing.

 getDateCategories (behName) {
   const allNames = behName.reduce((name, svt) => {
     return name.concat(svt.name); // Combine all svt.date arrays into single array
   }, []);

   return allNames; // Otherwise the function returns undefined
 }

I tried the below code:

getNames({name}){
    const nameValue = name;
    return(
      nameValue
    );
  }

and in render

const behaviour = this.state.data;
    console.log(behaviour);
    if (behaviour.hasOwnProperty('svt') === false) return null; // Wait till data is fetched before rendering

    const categories = this.getNames(behaviour.svt);

Could you please check?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants