Update data from model in custom component without reloading entire component?

Hi there,

I'm currently building a custom component with mapBox (i want more map styles and options than the retool mapbox component, which would, btw, be just awesome if it had at least several map styles).

So, I'm triggering some queries to get my markers ready to be injected in my mapbox custom component. I'm using Model to store my dynamic data and then use window.Retool.subscribe to get my data in my custom component js. Custom component shows and markers too.

But then, I want to filter markers by status and joboffer-title. Each time I'm filtering my marker the map entirely reloads.

<!DOCTYPE html>
<html>
<head>
   <meta charset="utf-8">
   <title>RH Maps</title>
   <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
   <link href="https://api.mapbox.com/mapbox-gl-js/v2.5.1/mapbox-gl.css" rel="stylesheet">
   <script src="https://api.mapbox.com/mapbox-gl-js/v2.5.1/mapbox-gl.js"></script>
   <style>
       body { margin: 0; padding: 0; }
        #map { position: absolute; top: 0; bottom: 0; width: 100%; }
     </style>
</head>

<body>
  
<div id="map"></div>
  
<script>

mapboxgl.accessToken = 'xxxxxxxxx';

const map = new mapboxgl.Map({
  container: 'map',
  style: 'mapbox://styles/mapbox/streets-v11',
  center: [2.1186, 46.4203],
  zoom: 4
});

map.on('load', () => {
  
  map.loadImage(
    'https://docs.mapbox.com/mapbox-gl-js/assets/custom_marker.png',
    (error, image) => {
      if (error) throw error;

  map.addImage('custom-marker', image);

  window.Retool.subscribe(function(model) {
    if(!model){ return }
    let locations = model.location
       map.addSource('points', {
        'type': 'geojson',
        'data': {
          'type': 'FeatureCollection',
          'features': locations             
          }
        }
      )
    }
  );
      
  map.addLayer({
    'id': 'points',
    'type': 'symbol',
    'source': 'points',
    'layout': {
      'icon-image': 'custom-marker',
      "icon-size": 0.5,
    'icon-padding' : 0,
    'icon-ignore-placement' : true
      // get the title name from the source's "title" property
      }
    });
  });
});

</script>
</body>
</html>

Is there a way I can update model.location so my markers change on the map without reloading everything? Retool mapBox component does it so maybe i'm missing something.

Thanks for your help

Hi @thomaspouma!

When I tried using the custom component you sent over I seemed to run into an issue where the map wasn't updating to reflect changes in the model. I'm wondering if something else is causing the component to reload. It looks like you have some show/hide logic, can you share the rest of the component settings?

Also, in case it ends up being helpful. You might want to consider using the .setData function on your source layer:

window.Retool.subscribe(function (model) {
        if (!model) {
          return;
        }
        
        let data = {
          type: "FeatureCollection",
          features: model.location,
        };
        
        if (map.isSourceLoaded("points")) {
          map.getSource("points").setData(data);
        } else {
          map.addSource("points", {
            type: "geojson",
            data,
          });
        }
      });

Hi @Kabirdas

Thanks a lot to take some time to check my issue.

Because i couldn't find a way to reload only markers data, each time i changed filter, i triggered a reload of the component at the end of my query13 query (which was gathering markers to be displayed).

Concerning the hide/show logic, i was hiding this map as my little HR tool was in production (with the retool mapbox component shown for live users).

I tried your piece of code with .setData logic and it works like a charm! It reloads markers without reloading the entire map, which is exactly what i was trying to do!

Thank you very much!