Angular Injectable service that is dependant on DOM element

231 Views Asked by At

I am just grasping Angular (6) framework, and it's quirks and features. And there is this one thing, that I would need, but as it seems, it goes against Angular paradigms - a service, that needs a reference to DOM node.

More specifically - Esri Map component. In it's constructor, it requires a DOM node - a place where the map will live. Since the Map is going to be the center thing in the application, it would be used by multiple components throughout the app. And for that, I would want it in a service. Question is - how would I do that? I made solution to this, but I would like to validate it with more experienced Angular devs.

So I have a MapComponent that would be like a singleton component - included only once in the App.

export class MapComponent implements OnInit {
  @ViewChild('map') mapElement:ElementRef;
  constructor(
    private renderer2: Renderer2,
    private mapService: MapService) { }
  ngOnInit() {
    // This is where I pass my DOM element to the service, to initialize it
    this.mapService.init(this.mapElement.nativeElement);
  }
}

And my mapService, that I would reference throughout other services

@Injectable()
export class MapService {
    private isInit:boolean = false;
    private map: __esri.Map = null;
    private mapView: __esri.MapView = null;
    init(domElement: ElementRef) {
        if (this.isInit) return Promise.resolve(); // A guard? 
        loadModules(["esri/Map", "esri/views/MapView", "esri/widgets/ScaleBar"])
            .then(([Map, MapView, ScaleBar]) => {
                this.map = new Map();
                this.mapView = new MapView({
                    map: this.map,
                    container: domElement // This is where I need DOM element
                });
            })
            .catch(err => {
                // handle any errors
                console.error(err);
            })
            .then(() => {
                this.isInit = true;
            });
    }
}

This does work, I just wonder, would this be a correct way to do it. I require these map objects to be accessible through other components, to add/remove/change map layers, draw/render geometries and other map things.

0

There are 0 best solutions below