Skip to content
This repository has been archived by the owner on Nov 6, 2024. It is now read-only.

esri loader Angular example #75

Closed
banchana opened this issue Jan 12, 2018 · 18 comments
Closed

esri loader Angular example #75

banchana opened this issue Jan 12, 2018 · 18 comments
Labels

Comments

@banchana
Copy link

Has anyone worked with esri-loader and have implemented successfully?

I am looking at the cli example (https://github.com/tomwayson/esri-angular-cli-example) listed on the esri-loader site (https://github.com/Esri/esri-loader) and it is still using the old libraries.

Is there a lot of difference in terms of how it is implemented in various files shown here in this link https://gist.github.com/tomwayson/e6260adfd56c2529313936528b8adacd?

Thanks!

@tomwayson
Copy link
Member

@banchana

Here is a recent commit that migrates an angular repo from using angular-esri-loader to esri-loader:

jccartwright/autogrid@3b4fcaf

@tomwayson tomwayson changed the title esri loader example esri loader Angular example Jan 12, 2018
@andygup
Copy link
Member

andygup commented Jan 12, 2018

@banchana here's a component that may help you out. It was last tested with esri-loader v1.5 + angular/cli: 1.5.0 + angular 5.0.1 . I'm looking at creating an updated repo, it's a work in progress.


import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';

import { loadModules } from 'esri-loader';

@Component({
  selector: 'app-esri-map',
  templateUrl: './esri-map.component.html',
  styleUrls: ['./esri-map.component.css']
})


export class EsriMapComponent implements OnInit {

  // for JSAPI 4.x you can use the "any for TS types
  public mapView: any;
  // public dojoConfig: any;

  // this is needed to be able to create the MapView at the DOM element in this component
  @ViewChild('mapViewNode') private mapViewEl: ElementRef;

  constructor() { }

  public ngOnInit() {

    return loadModules([
      'esri/Map',
      'esri/views/MapView'
    ]).then(([Map, MapView]) => {
      const mapProperties: any = {
        basemap: 'hybrid'
      };

      const map: any = new Map(mapProperties);

      const mapViewProperties: any = {
        // create the map view at the DOM element in this component
        container: this.mapViewEl.nativeElement,
        // supply additional options
        center: [-12.287, -37.114],
        zoom: 12,
        map // property shorthand for object literal
      };

      this.mapView = new MapView(mapViewProperties);
    })
      .catch(err => {
        console.log(err);
      });
  } 
}


@banchana
Copy link
Author

Thank you Tom and Andy for your prompt response to my issue. I will work towards implementing this and will provide my feedback to you once I am done. Appreciate your efforts.

@jwasilgeo
Copy link
Contributor

cc @jccartwright

@tomwayson
Copy link
Member

So @andygup

I see you're using any types in there. Are these instructions no longer valid?

https://github.com/Esri/esri-loader#4x-types

@banchana
Copy link
Author

Hey esri-loader team,
i have implemented the new stuff successfully.
I know your repo is still in progress, but I just wanted to let you know about one file that is still referencing the old angular-esri-loader, that was in esri-map.component.ts file. I updated that with what I thought should look like and was able to get my map working.
Thanks Much!
Banchana

@andygup
Copy link
Member

andygup commented Jan 12, 2018

@tomwayson good catch, yes the best practice is to continue to use the __esri.XYZ pattern. For reference, in case others aren't sure what this means, you can grab the ArcGIS JS API type definitions via: https://github.com/Esri/jsapi-resources/tree/master/4.x/typescript

@tomwayson
Copy link
Member

@banchana I'm going to close this issue since you seem to have it working, feel free to reopen if needed.

@Huwei1158
Copy link

Are there more advanced operations for both the angular and arcgis apis?Such as spatial query, and attribute query.I want to turn the arcgis API into a service, and then import the service in other components to get the classes in the service, such as app.map = map;App. Color = Color.I'm in other components, I just need to get this app, and I can, without using the loadModules function over and over again.

@jwasilgeo
Copy link
Contributor

@Huwei1158 please see the 2018 Esri Dev Summit presentation slides that discuss some of the topics you're asking about: https://github.com/Esri/jsapi-resources/tree/master/frameworks/angular#presentations

@tomwayson
Copy link
Member

@Huwei1158 esri-loader definitely complicates interaction w/ the ArcGIS API for JavaScript in that you do need to wrap any functions that use 'esri' modules in a call to loadModules(). This means that something that might have previously been synchronous like creating a new Extent() from JSON now becomes asynchronous b/c it has to be wrapped in a promise. For this reason, esri-loader works best when your app makes limited use of the ArcGIS API. You are following best practices by isolating all interaction w/ the ArcGIS API into a service, but I don't know of a better approach than for that service to expose async functions like newMap(elementId, options), newColor(colorJSON), etc.

@Huwei1158
Copy link

Huwei1158 commented Apr 12, 2018

@jwasilgeo Thank you. My level is limited, we are using arcgis api@3.18, and I want to turn it into the following:

import { Injectable } from '@angular/core';
import { loadScript, loadModules } from 'esri-loader'
@Injectable()
export class EsriService {
	map:any;
	config:any;
  constructor() { 
	var options = {
			url: 'http://218.241.213.230:8888/arcgis_js_api/library/3.18/3.18/init.js',
		};
		loadScript(options);
		loadModules(['esri/map','esri/config'],options).then(([Map,Config])=>{
//			this.map = Map;				
//			this.config = Config;
				this.map = function(a,b){
				return a*b
				} 
		});
//		this.map = function(a,b){
//		return a*b
//		}
  }
  

}

How do you break this callback function, get the Map in like this.map, output it, and then use it in the component.

@tomwayson
Copy link
Member

import { Injectable } from '@angular/core';
import { loadScript, loadModules } from 'esri-loader'

var options = {
  url: 'http://218.241.213.230:8888/arcgis_js_api/library/3.18/3.18/init.js',
};

@Injectable()
export class EsriService {

  esriConfig() {
		return loadModules(['esri/config'], options).then(([esriConfig]) => {
			return esriConfig;
		});
  },

  newMap(elementId, mapOptions) {
    return loadModules(['esri/map'], options).then(([Map]) => {
      return new Map(elementId, mapOptions);
    });
	}
}

Then in your component you might do something like:

mapService.esriConfig().then(esriConfig => {
	// TODO: do something w/ esriConfig here as needed, such as:
	esriConfig.defaults.io.corsEnabledServers.push('myserver');
	mapService.newMap('mapDiv',  { displayGraphicsOnPan:false }).then(map => {
		// TODO: do something w/ your map instance, like:
		map.on('extent-change', (delta, nexExtent) => {
			console.log(newExtent);
		});
	});
});

@Huwei1158
Copy link

Huwei1158 commented Apr 12, 2018

Thank you. This is not what I want. Two returns are too much trouble.Every module has to be written.I used to combine with webpack and use promise to get the module directly.But I won't with angular.Here's what I did with webpack:
1.this is map.js

import esriLoader from 'esri-loader';
import arcgis_url from 'Conf/arcgisUrl';

var app = {};

/*

初始化地图,id为需要绑定的map id
*/
app.initMap = function(id){
var that = this;
var p = new Promise(function(resolve, reject){
esriLoader.loadModules(['dojo/parser', 'esri/config', 'esri/map', 'esri/layers/ArcGISDynamicMapServiceLayer','esri/layers/FeatureLayer',
"esri/toolbars/MeasureTools", "dojo/_base/array", "esri/layers/LayerDrawingOptions", "dojo/on", "dojo/query",
"esri/tasks/query", "esri/tasks/QueryTask", "esri/layers/GraphicsLayer", "esri/tasks/FindTask","esri/tasks/FindParameters", 'esri/tasks/BufferParameters', 'esri/SpatialReference', "esri/geometry/Extent",
'esri/toolbars/navigation', 'esri/toolbars/draw', 'esri/tasks/GeometryService', 'esri/symbols/Font',
'esri/symbols/SimpleMarkerSymbol', 'esri/symbols/SimpleFillSymbol', 'esri/symbols/SimpleLineSymbol',
'esri/symbols/TextSymbol', 'esri/Color', 'esri/graphic', 'esri/tasks/LengthsParameters', 'esri/geometry/Point',
'esri/geometry/Polyline', 'esri/tasks/AreasAndLengthsParameters', 'dojo/dom-attr', 'esri/geometry/normalizeUtils', 'dojo/domReady!'], arcgis_url.initUrl)
.then(([parser, esriConfig, Map, ArcGISDynamicMapServiceLayer, FeatureLayer, deMeasureTools, arrayUtils, LayerDrawingOptions, on, query,
Query, QueryTask, GraphicsLayer,FindTask,FindParameters,BufferParameters, SpatialReference, Extent,
Navigation, Draw, GeometryService, Font, SimpleMarkerSymbol, SimpleFillSymbol, SimpleLineSymbol,
TextSymbol, Color, Graphic, LengthsParameters, Point, Polyline, AreasAndLengthsParameters, domAttr, normalizeUtils]) => {
console.log(arcgis_url);

parser.parse();
esriConfig.defaults.io.corsEnabledServers.push("218.241.213.230:6080");
esriConfig.defaults.io.corsEnabledServers.push("sampleserver1.arcgisonline.com");
esriConfig.defaults.geometryService = new GeometryService(arcgis_url.GeometryService);
 esriConfig.defaults.io.proxyUrl = "http://218.241.213.230:8888/Java/proxy.jsp";
	esriConfig.defaults.io.alwaysUseProxy = false;
// create map with the given options at a DOM node w/ id 'mapNode'
/*extent:new Extent(121,29,122,29.5, new SpatialReference({ wkid:4610 }))*/
that.map = new Map(id, {
	  	center: [121.4, 29.3],
 	zoom: 11,
 	logo:false,
});

//设置地图坐标系类型  
 var spatialReference = new SpatialReference(4610);  
 that.map.spatialReference = spatialReference;  
var basemap = new ArcGISDynamicMapServiceLayer(arcgis_url.basemap);
basemap.id = "basemap";
 that.map.addLayer(basemap);
 //自己封装的测量工具,在服务器arcgisapi中
 var measurTool = new deMeasureTools({
     map: that.map
 }, "map-tool");
 /*that.map.onClick = function(e){
 	var t = e;
 	console.log(e);
 };*/
 
 var fieldsSelectionSymbol =new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
 new SimpleLineSymbol(SimpleLineSymbol.STYLE_DASHDOT,
new Color([255, 0, 0]), 2), new Color([255, 255, 0, 0.5]));
that.Map = Map;
that.ArcGISDynamicMapServiceLayer=ArcGISDynamicMapServiceLayer;
that.FeatureLayer=FeatureLayer;
that.Navigation=Navigation;
that.arrayUtils = arrayUtils;
that.LayerDrawingOptions = LayerDrawingOptions;
that.SimpleFillSymbol=SimpleFillSymbol;
that.SimpleLineSymbol=SimpleLineSymbol;
that.Color=Color;
that.Query=Query;
that.Graphic=Graphic;
that.GraphicsLayer=GraphicsLayer;
that.esriConfig=esriConfig;
that.BufferParameters=BufferParameters;
that.SpatialReference=SpatialReference;
that.Extent=Extent;
that.GeometryService=GeometryService;
that.FindTask=FindTask;
that.FindParameters=FindParameters;
that.Point=Point;
that.SimpleMarkerSymbol=SimpleMarkerSymbol;
that.QueryTask=QueryTask;
that.query=query;
that.Draw=Draw;
that.normalizeUtils=normalizeUtils;
/*that.Draw=Draw;
that.Font=Font;
that.TextSymbol=TextSymbol;
that.LengthsParameters=LengthsParameters;
that.Polyline=Polyline;
that.AreasAndLengthsParameters=AreasAndLengthsParameters;
that.domAttr=domAttr;*/
resolve({
	ok:true
});
}).catch(err => {

console.error(err);
});
})
return p;
}
export default app;

2.this is other js:

import esris from './map';
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/js/bootstrap';
import arcgis_url from 'Conf/arcgisUrl';
var gpsMap = {};
gpsMap.mapRoad = function(roadName,serverUrl){
var map = esris.map;
//乡镇定位的函数
map.graphics.clear();//清空graphics
//实例化查询参数
var findParams = new esris.FindParameters();
findParams.returnGeometry = true;
findParams.layerIds = [2];//对地级城市和省记性查询
findParams.searchFields = ['GLMC'];//匹配图层中的字段属性
findParams.searchText = roadName;
var findTask = new esris.FindTask(serverUrl);
//进行查询
findTask.execute(findParams,showFindResult);
//查询结果匹配
function showFindResult(queryResult){
if (queryResult.length === 0) {
alert("查询无结果");
return;
}
console.log(queryResult)
$.each(queryResult, function(index, value) {
var pointSymbol = new esris.SimpleMarkerSymbol(//定义点符号
esris.SimpleMarkerSymbol.STYLE_CIRCLE, 10,
new esris.SimpleLineSymbol(esris.SimpleLineSymbol.STYLE_SOLID,
new esris.Color([255,0,0]), 1),
new esris.Color([255,0,0])
);
var outline= new esris.SimpleLineSymbol(esris.SimpleLineSymbol.STYLE_DASHDOT,new esris.Color([255, 0, 0]), 1); //定义面的边界线符号
var PolygonSymbol = new esris.SimpleFillSymbol(esris.SimpleFillSymbol.STYLE_SOLID, outline,new esris.Color([0, 255, 0, 1])); //定义面符号
var graphic ={}; //创建graphic
var locationPoint ={};//创建定位点
var geometry = value.feature.geometry;//获得该图形的形状
if(geometry.type == 'polygon'){
graphic = new esris.Graphic(geometry, PolygonSymbol);
locationPoint=geometry.getCentroid();
}
else if(geometry.type == 'point'){
graphic = new esris.Graphic(geometry, pointSymbol);
locationPoint=geometry;
}
//	map.graphics.add(graphic);
console.log(graphic)
console.log(locationPoint)
// map.centerAndZoom(locationPoint,1);
});
}
}

This is my ideal example.
But I don't know how to do it with a little bit of it?

@andygup
Copy link
Member

andygup commented Apr 12, 2018

@Huwei1158

Here's an example service that uses a promise esri-map.service.ts, and here's an example of the component that injects it esri-map.component.ts.

Note, the best practice is to defer loading of modules that aren't needed immediately, this is also referred to as lazy loading. Loading all the modules at the same time creates a performance bottleneck that can degrade the end user experience.

@tomwayson
Copy link
Member

@Huwei1158

Other than what I've suggested above, the pattern I describe here in this is the only other suggestion I have for you. If either of those don't work, then perhaps esri-loader is not the right solution for you.

@MohamadMousheimish
Copy link

Does anyone know why my esri-loader is not able to load GraphicsLayerView ??

@tomwayson
Copy link
Member

@MohamadMousheimish do you have a bin/fiddle/sandbox that demonstrates that?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

6 participants