highcharts / highcharts-react-native

Other
103 stars 79 forks source link

Need onMessage callback #33

Closed manohargunduboina-gep closed 4 years ago

manohargunduboina-gep commented 4 years ago

For a scenario I need onMessage callback when postMessage is called from webView

sebastianbochan commented 4 years ago

The callback should be defined in the wrapper and called in webview or you need to response message too?

manohargunduboina-gep commented 4 years ago

onMessage={(event) => this.props.onMessageCallback(JSON.parse(event.nativeEvent.data))} I need something like this in webView of wrapper so when I did a postMessage in webView I get the response to my native code

SaeedZhiany commented 4 years ago

This scenario is very useful. sometimes we need to call a method on React-Native side when the user clicks on the chart elements (e.g. Updating chart data by sending a new request to our server using a method written on react-native js methods, or navigate to another screen within app)

sebastianbochan commented 4 years ago

Thank you for details.

Will check what can I do and give you a feedback.

sebastianbochan commented 4 years ago

@SaeedZhiany @manohargunduboina-gep

I found the solution, but let me know if the message (from HTML to Webview) like string will be enough for your? Then you can run onMessage function and call your action.

PoC:


index.html

document.addEventListener('message', function (data) {
            Highcharts.charts[0].update(
                hcUtils.parseOptions(data.data)
            );
            window.ReactNativeWebView.postMessage('abc1');
        });

        window.addEventListener('message', function (data) {
            Highcharts.charts[0].update(
                hcUtils.parseOptions(data.data)
            );
            window.ReactNativeWebView.postMessage('abc');
        });

HighchartsReactNative.js

onMessage(event) {
        // run custom action
}
//...
<WebView
   //...parameters
  onMessage={this.onMessage}
/>

If yes, I will commit these changes.

manohargunduboina-gep commented 4 years ago

<WebView //...parameters onMessage={(event) => this.props.onMessage(event.nativeEvent.data)} />

I think something like this will be helpful so that I will set property onMessage with callback while sending props to HighchartsReactNative and I get the callback directly to my component and I need event too so that I will get the message which was sent from webview

string is enough for my requirement

sebastianbochan commented 4 years ago

@manohargunduboina-gep In the PoC its called only when you update the chart, do you need to also do that after chart init?

manohargunduboina-gep commented 4 years ago

Yes, for example if I have a button in webview every time I click the button I will call the window.ReactNativeWebView.postMessage('abc1'); with that I get a callback to my native code that button is clicked by onMessage event

If you want a PR I can do that

sebastianbochan commented 4 years ago

Feel free to do PR, I will review it tomorrow morning. If not, I will commit my changes.

sebastianbochan commented 4 years ago

@SaeedZhiany, Why did you not set it in chart options' by formatter?

SaeedZhiany commented 4 years ago

In one of my App I need to create labels from points value to show in charts (e.g. values on yaxis) because of the server response in just a number. for example, I need to show 1K instead of 1000 and more other converts that I have written the logics in my RN js side. my class is something like this:

class MyChartComponent extend React.PureComponent {

  private componentThis;

  constructore() {
    componentThis = this;
  }

  private formatter = () => {
    const {/* extract y value and unit from server response*/} = this;
    return componentThis.valueConverter(y, unit);
  }

  private valueConverter(val: number, unit: UnitEnum): string {
    // convert the val according to unit and return a label string
  }

}

I easily manage this case using react highcharts library with no problem and I'm looking for a solution that gives me the same functionality with minimum changes.

however, the ideal solution is something that we can call any function with an arbitrary number of parameters that might have any type. (I know webview has more limitations and calling arbitrary function is a very complex use case for this library)

is your current solution covers the usage above?

SaeedZhiany commented 4 years ago

Why did you not set it in chart options' by formatter?

because I have some interface and enum definitions that commonly used in RN sides and highcharts that are not necessarily primary js types and I want to have them in one place for keeping future changes consistence.

SaeedZhiany commented 4 years ago

My current (but obviously dirty) solution is rewriting the needed functions and interfaces purely in js and send all of them to Webview, so the Webview acts standalone and manages everything (sending requests and convert data and ...)

The logics and function I have mentioned above are also used in my react web application and they change over time, so it's very important to me to not rewrite them every time, because additional to the above problems I'm using typescript in my both project, so converting all the functions and interfaces to pure js is very hard and impossible to maintain.

sebastianbochan commented 4 years ago

@manohargunduboina-gep I sent you a review in PR.

@SaeedZhiany It looks more complex than I expected, but in the Highcharts it should work by default.

Demo:

If it will not work, try to set tickInverval: 1000 param

Could you paste your data?

SaeedZhiany commented 4 years ago

It looks more complex than I expected, but in the Highcharts it should work by default.

yeah exactly and it's because of the different nature of webview and regular RN project and lack of communication technologies between them.

As I mentioned before convert 1000 -> 1 K is one of my use cases, sometimes the data is computer-related measure like RAM storage so I need to convert my data to MB or GB, and so many other cases for different conversions, so I couldn't use highchart options to handle all the cases. in my react web app I wrote my custom function and simply call it within formatter function. now I need to reuse my function in RN and this library.

Could you paste your data?

Sorry, I can't share my data models, but in an overall picture, it has a custom data structure (like most other project) that I want to show some of its fields on a chart. you can assume something like below

[{
  y: number,
  timestamp: string
}]

in a general manner, it can be assumed even more complex data.

SaeedZhiany commented 4 years ago

@sebastianbochan

I just found an exciting library to manage functions invocations between react-native and webview. I put its links here and if you want, take a look at the library.

react-native-webview-invoke

sebastianbochan commented 4 years ago

Thanks @SaeedZhiany !

jj-julia commented 4 years ago

@manohargunduboina-gep @sebastianbochan @SaeedZhiany It would be great if you could show us an example for click event being used with the onMessage prop.

Thanks

manohargunduboina-gep commented 4 years ago
chart: {
            type: 'pie',
             events: {
              drilldown: function (e) {
                     if (!e.seriesOptions) {
                          window.ReactNativeWebView.postMessage(window.data)
                     }
                }
            }
}
<HighchartsReactNative
        useCDN={true}
        options={this.state.graph}
        useSSL={true}
        modules={modules}
        onMessage={data => this.props.drillDown(JSON.parse(data))}
        data={data}
        loader={true}
      />

@jj-julia Thats how I've used it for drilldown