Kepler.gl: Add new dataset and config layer to map keeping old datasets and config layers

Created on 24 Jan 2019  Â·  14Comments  Â·  Source: keplergl/kepler.gl

I am calling the addDataToMap as in the vis-academy example.
However when I call the function again when there is some user input the old data is lost, except when I remove the config version then the data is kept but the config mapState is lost.

For example if the config is this:
let mapConfig = self.getMapConfig();
mapConfig.config.visState.layers = (a layer array containing all the config visState layers for each dataset)
delete mapConfig.version;
self.props.dispatch(
addDataToMap({
datasets: dataset,
config: mapConfig,
options: { readOnly: false }
})
);
The map state is reset, and if the mapConfig.version is not removed the the previous datasets are lost.

enhancement investigation needed

All 14 comments

Hi @rfockema, would you be able to provide an example where we can reproduce your issue?

thank you

To Reproduce

Follow the https://github.com/uber-common/vis-academy/blob/kepler.gl/src/demos/kepler.gl/3-load-config/src/app.js example
Modify the replaceData function to add data and a config visstate layer instead of just replacing the old data.

Something like:

replaceData = () => {
  // Use processCsvData helper to convert csv file into kepler.gl structure {fields, rows}
    const data = Processors.processCsvData(nycTripsSubset);
    // Create dataset structure
    const dataset = {
      data,
      info: {
        id: 'new_id'
        // this is used to match the dataId defined in nyc-config.json. For more details see API documentation.
        // It is paramount that this id mathces your configuration otherwise the configuration file will be ignored.
      }
    };

    // read the current configuration
    let config = this.getMapConfig();
    config.config.visState.layers.push({...someLayer, config:{dataId:'new_id'}});

    // addDataToMap action to inject dataset into kepler.gl instance
    this.props.dispatch(addDataToMap({datasets: dataset, config}));
  };

Is it possible to add a dataset with a config visstate layer while still keeping the old data and config layer?

Is it possible to dynamically update the config without adding data?

When I try this the old data gets replaced, unless I remove config.version property, but then the mapState is lost.

This can be solved with the vis-state-actions:
layerConfigChange
Update layer base config: dataId, label, column, isVisible

ActionTypes: ActionTypes.LAYER_CONFIG_CHANGE
Updaters: visStateUpdaters.layerConfigChangeUpdater
Parameters

oldLayer Object layer to be updated
newConfig Object new config
Returns {type: ActionTypes.LAYER_CONFIG_CHANGE, oldLayer: oldLayer, newConfig: newConfig}

Can I please get an example of how to use this action?
Specifically the format of the oldLayer object parameter required?

Should this work?

const mapConfig = this.getMapConfig();
    this.props.dispatch(
      layerConfigChange(mapConfig.config.visState.layers[0], {
        isVisible: false
      })
    );

I get this error:
TypeError: oldLayer.updateLayerConfig is not a function

Should this work?

const mapConfig = this.getMapConfig();
    this.props.dispatch(
      layerConfigChange(mapConfig.config.visState.layers[0], {
        isVisible: false
      })
    );

I get this error:
TypeError: oldLayer.updateLayerConfig is not a function

@rfockema
Unfortunately your code is not gonna work because layerConfigChange expects an actual Layer and not a simple javascript object (which you are retrieving from getMapConfig) as the one you are passing.

One more thing, reading your issue description, what are you trying to achieve exactly? I see you are passing the same configuration and datasets from the previous addDataToMap call, is that correct or am I missing something?

I also have this problem. Is there any update on how we can use addDataToMap without replacing the old dataset?

Hi
In this way I succeeded to add a new dataset and to retain the previous one
const config = this.getMapConfig();
config.config = nycConfig;
this.props.dispatch(addDataToMap({datasets: dataset, config}));

I'm having this issues as well. Adding a new dataset with any config or options causes it to replace all prevously added datasets with the new one.

EDIT:

It's difficult for me to implement the same solutions as others, as I'm trying to add these datasets asyncronously

@bragilev
How did you pass the new dataset? I am in a similar situation.

const dataset2 = {
      data: {
        rows: [2, "2016-01-15 16:18:03 +00:00,2016-01-15 16:50:30 +00:00",2,12.42,76.962509,8.477347,76.969429,8.482663]
      },
      info: {
        id: "my_data"
      }
    };

this.props.dispatch(addDataToMap({ datasets: dataset2, config }));

const config = this.getMapConfig();
    config.config = nycConfig;

@ajinkabeer
I was able to do it deleting the config version like @rfockema. If it helps...
EDIT:
I can drop the code, but it very similar to what has been posted

You need to define two different layers with two different data_ids in your
configuration file

On Fri, Jul 19, 2019, 1:12 PM Ajin Kabeer notifications@github.com wrote:

@bragilev https://github.com/bragilev
How did you pass the new dataset? I am in a similar situation. I created a
new dataset named dataset2 and assigned config.config = nycConfig like
you did.It doesn't work.Could you please explain to me how you did it?

const dataset2 = {
data: {
rows: [
2,
"2016-01-15 16:18:03 +00:00,2016-01-15 16:50:30 +00:00",
2,
12.42,
76.962509,
8.477347,
76.969429,
8.482663
]
},
info: {
id: "my_data"
}
};

this.props.dispatch(addDataToMap({ datasets: dataset2, config }));

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/keplergl/kepler.gl/issues/343?email_source=notifications&email_token=ADILFQA3M6CFXC5NS7CWDH3QAGHSFA5CNFSM4GSB5B3KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2LG6QI#issuecomment-513175361,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ADILFQDOMBWJLO7NX2INL4TQAGHSFANCNFSM4GSB5B3A
.

EDIT: Changed visStateUpdaters.updateVisDataUpdater to combinedUpdaters.addDataToMapUpdater and adjusted code to better fit

I found another way around for those looking for something that doesn't require passing the original config directly.

Here I'm creating a custom reducer, meant to be an alternative to the addDataToMapUpdater
It calls the original, and then puts all the stuff I still want back into the returned state

// relevant imports
import keplerGlReducer, { combinedUpdaters } from 'kepler.gl/reducers'

const customizedKeplerGlReducer = keplerGlReducer
  .initialState({
    // I'm just adding a custom layer here
    // not super relevant but if your curious about this I'm down to answer questions!
    visState: { layerClasses: Layers.LayerClasses },
    uiState: { currentModal: null },
  }).plugin({
    APPEND_VIS_DATA: (state, action) => {
      const newState = combinedUpdaters.addDataToMapUpdater(state, action)
      const mergedState = {
        ...state,
        ...newState,
        visState: {
          ...state.visState,
          ...newState.visState,
          layerClasses: { ...state.visState.layerClasses },
          layerData: [...state.visState.layerData, ...newState.visState.layerData],
          datasets: { ...state.visState.datasets, ...newState.visState.datasets },
          layers: [...state.visState.layers, ...newState.visState.layers],
        },
      }
      mergedState.visState.layerOrder = mergedState.visState.layers.map((l, i) => i)
      return mergedState
  })

So if you want something similar, create a new reducer like above, then create an action that calls that type.

Added keepExistingConfig to options to allow keeping old datasets and config layers

https://github.com/keplergl/kepler.gl/pull/619

@Harrisandwich Solution worked for me, thanks. Even though we should have to do this. I think this is a problem with addDataToMap

Was this page helpful?
0 / 5 - 0 ratings