Victory-native: Changing Tooltip behaviour: disappear only when tap on another data point

Created on 13 Feb 2019  路  4Comments  路  Source: FormidableLabs/victory-native

Bugs and Questions

Checklist

  • [x] This is a victory-native specific issue. (Issues that _also_ appear in victory should be opened here)

  • [x] I have read through the FAQ and Guides before asking a question

  • [x] I am using the latest version of victory-native

  • [x] I have checked to make sure that my versions of react-native and react-native-svg are compatible with this version of victory-native. Read about version requirements

  • [x] I've searched open issues to make sure I'm not opening a duplicate issue

The Problem / Question

I am trying to change the tooltip behaviour. Currently, tooltip only appear when you keep pressing on a data point (for example in victory-scatter), once you lift your finger the tooltip will disappear. So, what I am trying to achieve is to keep the tooltip appear on first press, then only hide it when I press on another data point. Any pointer as to how to achieve this? Tried using custom events as follow:

<VictoryScatter
    key={i}
    data={data}
    size={10}
    labels={d =>
        d.y.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
    }
    labelComponent={
        <VictoryTooltip
            style={{
                fontSize: 20,
                fill: commonStyles.bodyColor,
                textAlign: 'left',
                touchAction: 'none'
            }}
            orientation="top"
            flyoutStyle={{ fill: commonStyles.optionMenuColor }}
            standalone={false}
            renderInPortal={false}
        />
    }
    events={[
        {
            target: 'data',
            eventHandlers: {
                onPressIn: (evt, pressedProps) => {
                    const selectedDataIndex = pressedProps.index
                    return [
                        {
                            eventKey: 'all',
                            target: 'labels',
                            mutation: props => {
                                let activeState = true
                                if (props.active === true) {
                                    activeState = null
                                }
                                return props.index ===
                                    selectedDataIndex
                                    ? { active: activeState }
                                    : null
                            },
                        },
                    ]
                },
                onPressOut: (evt, pressedProps) => {
                    const selectedDataIndex = pressedProps.index
                    return [
                        {
                            eventKey: 'all',
                            target: 'labels',
                            mutation: props =>
                                props.index === selectedDataIndex
                                    ? { active: props.active }
                                    : null
                        },
                    ]
                },
            },
        },
    ]}
/>

It works, but not stable. Sometime, after I press the first data point and tooltip appear, the subsequent onPressIn events will not be triggered hence the first tooltip won't disappear. Sometime, once the graph is rendered, events are not triggered at all. For more info, I am rendering >1 victory-scatter and victory-line in 1 victory-chart parent.

I read about past issues where nesting victory chart as scrollview children could cause react-native-svg not responding, doubt that's the issue in this case, as the "unstable" issue remain even when I replace scrollview with normal view.

Has anyone tried to accomplish this use case? or perhaps any pointer on how I could achieve this?

Most helpful comment

You did a good job actually
just a small logic mistake
i changed your code to below and it worked

                                    onPressIn: (evt, pressedProps) => {
                                        const selectedDataIndex = pressedProps.index
                                        return [
                                            {
                                                eventKey: 'all',
                                                target: 'labels',
                                                mutation: props => {
                                                    let activeState = true
                                                    if (props.active === true) {
                                                        activeState = null
                                                    }
                                                    return props.index ===
                                                        selectedDataIndex
                                                        ? { active: activeState }
                                                        : { active: false } // changed this line from null
                                                },
                                            },
                                        ]
                                    },

All 4 comments

I'm impressed you got tooltips to work at all. I've been banging my head against them for awhile, and there are two open issues about it:
FormidableLabs/victory-native#350
FormidableLabs/victory-native#307

You did a good job actually
just a small logic mistake
i changed your code to below and it worked

                                    onPressIn: (evt, pressedProps) => {
                                        const selectedDataIndex = pressedProps.index
                                        return [
                                            {
                                                eventKey: 'all',
                                                target: 'labels',
                                                mutation: props => {
                                                    let activeState = true
                                                    if (props.active === true) {
                                                        activeState = null
                                                    }
                                                    return props.index ===
                                                        selectedDataIndex
                                                        ? { active: activeState }
                                                        : { active: false } // changed this line from null
                                                },
                                            },
                                        ]
                                    },

The above solution is not working for me any idea how to achieve this ?
EDIT-
This worked for me - >
events={[
{
target: 'data',
eventHandlers: {
onTouchEnd: () => { }, // Override default tooltip
onPress: () => {
return [
{
target: "labels",
eventKey: "all", // deactivate all active tooltips
mutation: () => ({ active: false })
},
{
target: "labels", // activate current tooltip eventKey
mutation: () => ({ active: true })
}
];
}
}
}
]}

How do I achieve the same behaviour using the voronoi container?
The events prop on VictoryVoronoiContainer seems to be different

<VictoryChart
    containerComponent={
        <VictoryVoronoiContainer
            voronoiDimension="x"
            labels={({datum}) => !datum.continuous ? datum.l : null}
            labelComponent={
                <VictoryTooltip
                    constrainToVisibleArea
                    renderInPortal={false}
                    cornerRadius={5}
                    centerOffset={{ x: 20, y: -20 }}
                    flyoutStyle={{ fill: 'white' }}
                />
            }
        />
    }
>
Was this page helpful?
0 / 5 - 0 ratings