Search code examples
svelteopenlayers-6svelte-componentsvelte-store

svelte two components to access same object


In my app, I have a route map.svelte

This has two child components: Map.svelte and LayerSelector.svelte

Map.svelte creates an OpenLayers map instance. LayerSelector.svelte needs to access this instance.

I am declaring the map instance in map.svelte and binding it to the two components, but do not appear to be able to access it in LayerSelector.svelte

map.svelte:

<script>
  import Map from '../components/Map.svelte';
  import MapLayerSelectorDialog from '../components/LayerSelector.svelte';
  let map;
</script>

<div class="map" id="map">
 <Map organisation={organisation} meta={meta} 
  showBackControl="true" showEditControl="true" showSearchControl="true"
  bind:map={map}
  on:mapready={initLayerSelector(map)}
  on:map-back={back=goBack}
  on:featureselected={featureSelected}
  on:togglelayerselector={toggleLayerSelector}
  on:togglemapsearch={toggleMapSearch}
  on:togglemapeditcontrol={toggleMapEdit}
 />
</div>

<MapLayerSelectorDialog bind:showDialog={showLayerSelectorDialog}
  bind:meta = {meta}
  bind:map={map}>
</MapLayerSelectorDialog>

Map.svelte:

export let map = null;
...
onMount(async () => {
  map = await initMap ('map', organisation, meta, startCoords);
});
...

initMap.js

export async function initMap (div, organisation, meta, startCoords) {
  var map = new Map({
    target: div, //'map',
    view: new View({
      center: fromLonLat ([1330601.87, 7916443.12]),
      zoom: 12,
    }),
  });
  addLayers (map, meta);
});

LayerSelector.svelte:

<script>
export let map
</script>
{#each map.getLayers() as layer}
  <p>{layer.get('name')}</p>
{/each}

Where might I be going wrong? Do I need to put the OpenLayers map instance in a writeable store mayebe?


Solution

  • Per se, your code should work. You can have two-way bindings of the variable to two separate child components like you are doing and then have one of them initialize it.

    I created a REPL that illustrates that it's possible.

    When you say you are not able to access the variable, what do you mean? You get an unexpected value or an error?

    I suspect that the problem you have is that map will be undefined for a brief period before onMount runs. And LayerSelector will throw an error if map is not set.

    If that is the issue, replacing map.getLayers() with e.g. map ? map.getLayers() : [] will fix it.

    That said, having a lot of two-way bindings makes for unclear data flow. I'd consider initializing the variable in map.svelte and then simply passing it to the other components to simplify the data flow a bit.