Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ol.control implementation #45

Closed
achimha opened this issue Feb 11, 2017 · 10 comments
Closed

ol.control implementation #45

achimha opened this issue Feb 11, 2017 · 10 comments

Comments

@achimha
Copy link
Contributor

achimha commented Feb 11, 2017

I started looking into the unfinished control implementations.

There are a few questions. First of all, I don't think you can derive the classes from the OL classes as this breaks the @Input() parameter setting. So I changed it to the instance method used elsewhere. Next, the question is whether to use transclusion with <ng-content>. I couldn't get it to work so I went for this solution which uses the component's DOM element:

@Component({
  selector: 'aol-control-mouseposition',
  template: ``
})
export class ControlMousePositionComponent implements OnInit, OnDestroy {
  instance: control.MousePosition;
  @Input() coordinateFormat: CoordinateFormatType;
  @Input() projection: ProjectionLike;
  target: Element;

  constructor(
    @Host() private map: MapComponent,
    private element: ElementRef
  ) {
  }

  ngOnInit() {
    this.target = this.element.nativeElement;
    // console.log('ol.control.MousePosition init: ', this);
    this.instance = new control.MousePosition(this);
    this.map.instance.addControl(this.instance);
  }

  ngOnDestroy() {
    // console.log('removing aol-control-mouseposition');
    this.map.instance.removeControl(this.instance);
  }
}

In order to style it, you will need the piercing CSS selector ( :host /deep/) which is probably OK. Any thoughts on how to do the controls implementation?

@achimha
Copy link
Contributor Author

achimha commented Feb 13, 2017

With a wrapper for the <ng-content>, it actually does work. Here's my generic ol.Control implementation that displays the content. Styling with selector piercing.

import { Component, ElementRef, Host, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { control } from 'openlayers';
import { MapComponent } from '../map.component';

@Component({
  selector: 'aol-control',
  template: `<div #wrapper><ng-content></ng-content></div>`
})
export class ControlComponent implements OnInit, OnDestroy {
  public componentType: string = 'control';
  instance: control.Control;
  element: Element;

  @ViewChild('wrapper') wrapper: ElementRef;

  constructor(
    @Host() private map: MapComponent
  ) {
  }

  ngOnInit() {
    this.element = this.wrapper.nativeElement.children[0];
    this.instance = new control.Control(this);
    this.map.instance.addControl(this.instance);
  }

  ngOnDestroy() {
    this.map.instance.removeControl(this.instance);
  }
}

@quentinlampin
Copy link
Owner

About the subclassing of ol.control classes : you're right. We moved away from this design in every other component but I haven't found the time to change the controls yet.

Regarding the transclusion and the wrapper solution, I'm not sure I understand what you're trying to achieve. Could you provide an example so I understand what's at stake and come back with meaningful ideas ?

@achimha
Copy link
Contributor Author

achimha commented Feb 13, 2017

My (rather big now) PR has the control reimplementation included.

With the control class copied above, I can do this:

     <aol-control>
            <div id="settingscontrol" class="ol-control ol-unselectable">
                <button (click)="showSettings = true">
                    <i class="fa fa-bars"></i>
                </button>
            </div>
        </aol-control>

The only problem I see is that I get an additional wrapper div. I don't know a way around that as I can't get hold of the <ng-content> without an element to reference. It's probably OK but I don't like the extra div. You can see in my class that I get hold of the #wrapper element and then pass its first child to the OL API.

@quentinlampin
Copy link
Owner

Hmm, I'm not a fan of the wrapper div solution either.

Have you tried passing the ElementRef to the component constructor and then accessing the transcluded content like this ?

 constructor(
    @Host() private map: MapComponent,
    private element: ElementRef
  ) {
  }
[...]

this.element.nativeElement.childNodes[0]

@achimha
Copy link
Contributor Author

achimha commented Feb 13, 2017

Actually this works as well. Thanks!

@achimha achimha closed this as completed Feb 13, 2017
@achimha
Copy link
Contributor Author

achimha commented Feb 13, 2017

Came up with another issue with this approach (taking the first child). I created a an implementation of ol.Overlay. Among its parameters is the map position for which I used the existing <aol-coordinate>. Now the question is how to differentiate between the content of the overlay (inserted via transclusion) and the coordinate. Example markup:

        <aol-overlay>
            <div><h1>THIS IS AN OVERLAY</h1></div>
            <aol-coordinate [x]="center[0]" [y]="center[1]" [srid]="'EPSG:4326'"></aol-coordinate>
        </aol-overlay>

The approach taken is to get an ElementRef and pass the first child to the OL control. Obviously it works (coordinate is the second) but is this a good approach?

@achimha achimha reopened this Feb 13, 2017
@achimha
Copy link
Contributor Author

achimha commented Feb 13, 2017

What about enumerating children until we get the first one that does not start with aol-? Uglier? Less ugly? 😄

@quentin-ol
Copy link
Collaborator

quentin-ol commented Feb 13, 2017 via email

@achimha
Copy link
Contributor Author

achimha commented Feb 13, 2017

I like the <aol-content> approach. That's at least clean. I'll implement it like this.

@achimha
Copy link
Contributor Author

achimha commented Feb 14, 2017

Implemented and documented as part of my latest PR.

@achimha achimha closed this as completed Feb 14, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants