infra-geo-ouverte / igo2-lib

Librairie Infrastructure Géomatique Ouverte 2.0 (IGO-2) / Open GIS Infrastructure 2.0 Library
https://infra-geo-ouverte.github.io/igo2-lib/
40 stars 25 forks source link

igo-map-field component does not display the map #56

Closed iamkinetic closed 7 years ago

iamkinetic commented 7 years ago

I'm trying to incorporate the IgoMapField component in one of our component. My issue is that the map is not being displayed under the input control.

Here is what I've done so far :

I've copied the igo-lib _context.json file to our project.

html file : <div class="igo-map-field-container"> <igo-map-field formControlName="location" placeholder="Localisation" [decimals]="8" [readonly]="false" [layers]="(map.layers$ | async) | clone" [view]="contextService.context$.value ? (contextService.context$ | async).map.view : undefined"> </igo-map-field> </div>

ts file:

I've added the contextService in the constructor and a IgoMap variable (named 'map') in my component.

In ngOnInit, i load the context like so : this.contextService.loadContext('_default');

All I can see of the map part of the component is the open layers button.

Here's my console's log :

zone.js:1990 XHR finished loading: GET "http://localhost:4200/contexts/_default.json".

I'm not getting any error and I have no idea what I'm doing wrong.

iamkinetic commented 7 years ago

This is the result I'm getting :

image

cbourget commented 7 years ago

Is your contextService private or public? It needs to be public in order to be accessed in th template file.

iamkinetic commented 7 years ago

It is public. I've just noticed I can select a new location if I click where the map should be displayed.

This is the component where I'm using IgoMapField if you need to check my code : FireHydrantComponent

cbourget commented 7 years ago

I won't be available for most of today but as soon I get a chance, I'll take a look at it.

cbourget commented 7 years ago

I see that you use the format lat/lon instead of lon/lat. That may explain why there is nothing at 46.20083, -70,621622. The MSP base maps covers the province of Quebec only and that is out of bound.

iamkinetic commented 7 years ago

I've tried inversing the lat/long values with little success. I can see the pin point icon, but the map is still not being displayed : This screenshot is showing the map fully zoomed out.

Btw, we've been following the ISO6709 standard in our newer softwares which state that a geographic point location should be displayed as lat/long rather than long/lat.

cbourget commented 7 years ago

Can you show where you set your context and what it looks likes?

cbourget commented 7 years ago

Note that we use lon/lat because that's what OL uses but we could make this component support both formats.

iamkinetic commented 7 years ago

We'll make some features requests in the next few days/weeks. I'll make sure to include this one.

iamkinetic commented 7 years ago

My context is loaded in the ngOnInit : this.contextService.loadContext('_default');

And the context itself is the very same one found in the igo2-lib project. It is located in the src\contexts folder.

I've also tried using the same one you had setup when we started the demo a month ago. Same result.

 ngOnInit() {

    /*this.contextService.loadContext('_default');*/

    const layer1 = {
      'source': {
        'title': 'Fond de carte du Québec',
        'type': 'xyz',
        'url': 'https://geoegl.msp.gouv.qc.ca/cgi-wms/mapcache.fcgi/tms/1.0.0/carte_gouv_qc_ro@EPSG_3857/{z}/{x}/{-y}.png'
      }
    };

    this.contextService.setContext({
      'uri': 'default',
      'title': 'Default Context',
      'map': {
        'view': {
          'projection': 'EPSG:3857',
          'center': [-70.685006, 46.116211],
          'zoom': 14,
          'minZoom': 6,
          'maxZoom': 17
        }
      },
      'layers': [layer1]
    } as DetailedContext);
  }
cbourget commented 7 years ago

I just tested it with the exact same config as you it it worked. Are you sure "contextService.setContext" has been called once when accessing the page with the map field? Is that ngOnInit defined on the component containing the map field or a parent component?

iamkinetic commented 7 years ago

Should it be called on the parent component?

The setContext method is currently called in the children's ngOnInit. There may be more than one child. The map field is also in the children component.

This child component is named FireHydrantComponent : FireHydrantComponent

cbourget commented 7 years ago

Contexts are generally app wide things. They are often set in a component near the root component of your app. In your case, a context doesn't seem necessary, unless you have other maps in your app with the same layers and view, for example. Then it would be a good idea to set the context in a parent component.

Back to your problem problem... The map who's layers you clone has no layer. It's a new IgoMap but you never actually add the context layers to it. The code you used to pass the layers to the map-field is taken from the demo app in the library but in that app, there is a map browser bound to the context with a directive and that is why the context layers are added to that map (then cloned and passed to the map field). It was done this way to avoid duplicating some code but it won't work in your case. I think the demo-app in the library should be modified to avoid confusion.

Now, what you can do is create layer objects (using the datasource and layer services) and pass them to the map-field. The layer config that'll give to those services can be taken from the context (it would make sense if you create it in a parent component for reusability). If you don't go the context way, simply create layers with configs hardcoded directly in your component then give them to the map-field.

As for the map view, you may take it from the context or define it directly in your component but you won't need any service since a map is not a class instance.

Check the method "addLayerToMap" here https://github.com/infra-geo-ouverte/igo2-lib/blob/master/src/lib/context/shared/layer-context.directive.ts if you need help creating your layers.

iamkinetic commented 7 years ago

It's finally working. Here is what I did in my child component ngOnInit :

const layer1 = {
  'source': {
    'title': 'Fond de carte du Québec',
    'type': 'xyz',
    'url': 'https://geoegl.msp.gouv.qc.ca/cgi-wms/mapcache.fcgi/tms/1.0.0/carte_gouv_qc_ro@EPSG_3857/{z}/{x}/{-y}.png'
  }
};

this.contextService.setContext({
  'uri': 'default',
  'title': 'Default Context',
  'map': {
    'view': {
      'projection': 'EPSG:3857',
      'center': [-70.6850, 46.116211],
      'zoom': 14,
      'minZoom': 6,
      'maxZoom': 17
    }
  },
  'layers': [layer1]
} as DetailedContext);

this.addLayerToMap(layer1);

addLayerToMap is pretty much the same method found in the directive you were mentionning in your previous reply.

I'm not so sure It's right, but it works.

cbourget commented 7 years ago

Great! You might not need to use a context in your case but it's fine to use one. The other way around would be to simply define the map view in a property of your component and pass it to the map-field as an input.

Maybe the addLayerToMap method should be made public and moved somewhere else in the library for reusability. I'll let you know if it happens.