2013-07-09 51 views
9

Angular uygulamasında ArcGIS JavaScript API kullanmayı deniyorum. Gördüğüm gibi, Dojo kullanıyor. Yani, böyle Açısal yönergede gelen ArcGIS başlatmak çalışıyorum:AngularJS + ArcGIS

Uncaught TypeError: Cannot call method 'apply' of null 
: Ben fare tekerleğini kaydırarak yakınlaştırmak için çalışırken, bu hatayı alıyorum çünkü bu şekilde Görünüşe
link: function (scope, element, attrs) { 
    dojo.require('esri.map'); 
    var init = function() { 
     console.log('dojo is ready'); 
     var map = new esri.Map("map-container", { 
     center: [-111.3797, 56.7266 ], 
     zoom: 16, 
     basemap: "streets" 
     }); 
     map.enableScrollWheelZoom() 

    }; 
    dojo.addOnLoad(init); 
    } 

% 100 doğru olduğunu

Sorum, bir Angular uygulamasında ArcGIS işlevselliğinin düzgün şekilde nasıl enjekte edileceğidir?

cevap

12

Sanırım buna çok 'AngularJS' stil yaklaşımı aşağıdaki gibi bir şey olurdu. (burada kesişin http://jsfiddle.net/technicolorenvy/2Ke62/4/)

angular-ui-router'u kullanmayı seviyorum, ancak bu yaklaşım aynı zamanda Angular'ın $routeProvider ile çalışacaktır. Buradaki sihir, devam etmeden önce bir sözün çözülünceye kadar isteğe bağlı olarak 'bekle' olacak çözme nesnesidir.

angular.module('webApp', ['ui.router']) 
    // module (app) config 
    .config(function ($stateProvider, $urlRouterProvider) { 

     $urlRouterProvider.otherwise('/map'); 

     $stateProvider.state('map', { 
      url: '/map', 
      template: '<div id="map"></div>', 
      controller: 'MapCtrl', 
      resolve: { 
       promiseObj: function ($q, $rootScope, wish) { 
        var deferred = $q.defer(), 
         deps = { 
          Map: 'esri/map', 
          FeatureLayer: 'esri/layers/FeatureLayer', 
          InfoTemplate: 'esri/InfoTemplate', 
          SimpleFillSymbol: 'esri/symbols/SimpleFillSymbol', 
          SimpleRenderer: 'esri/renderers/SimpleRenderer', 
          SimpleMarkerSymbol: 'esri/symbols/SimpleMarkerSymbol', 
          ScaleDependentRenderer: 'esri/renderers/ScaleDependentRenderer', 
          Color: 'dojo/_base/Color' 
         }; 

        wish.loadDependencies(deps, function() { 
         deferred.resolve(); 
         if (!$rootScope.$$phase) { 
          $rootScope.$apply(); 
         } 
        }); 

        return deferred.promise; 
       } 
      } 
     }); 
    }); 

Yukarıda görebileceğiniz gibi

, bir resolve pervane olan bir map devlet var. Ardından, ArcGIS/Dojo bağımlılıklarınızı temsil eden bir nesne oluşturabilir ve bunu wish.loadDependencies numaranıza aktarabilirsiniz (aşağıya bakınız).

Eğer senin kadar (bütün ArcGIS/Dojo FNS doğrudan çağrı, tüm bağımlılıkları sizin MapCtrl yılında bundan sonra dojosu en require

angular.module('webApp') 
    // service that deals w/ our dojo require 
    .service('wish', function() { 

     // it's not require... it's a wish? 
     var wish = {}; 

     function _loadDependencies(deps, next) { 
      var reqArr = _.values(deps), 
       keysArr = _.keys(deps); 

      // use the dojo require (required by arcgis + dojo) && save refs 
      // to required obs 
      require(reqArr, function() { 
       var args = arguments; 

       _.each(keysArr, function (name, idx) { 
        wish[name] = args[idx]; 
       }); 

       next(); 
      }); 
     } 

     return { 
      loadDependencies: function (deps, next) { 
       _loadDependencies(deps, next); 
      }, 

      get: function() { 
       return wish; 
      } 
     }; 
    }); 

yoluyla yüklenen bir kez çözüme kavuşturulacağını bir söz dönecektir q açabilir normalde), wish.get() tarafından döndürülen nesneye eklendiklerinden, uygulama yapılandırması sırasında oluşturulmuş olan deps nesnesinde kullandığınız tuşlar ile. aşağıdaki Ne

burada (https://developers.arcgis.com/en/javascript/jssamples/renderer_proportional_scale_dependent.html) bulunan örnek

angular.module('webApp') 
    // our map controller 
    .controller('MapCtrl', function ($rootScope, $scope, wish) { 

     var w = wish.get(), 
      greenFill = new w.Color([133, 197, 133, 0.75]), 
      greenOutline = new w.Color([133, 197, 133, 0.25]), 
      layer, 
      markerSym, 
      renderer1, 
      renderer2, 

      CROPS_URL = 'http://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/USA_County_Crops_2007/FeatureServer/0'; 

     $scope.map = new w.Map('map', { 
      center: [-98.579, 39.828], 
      zoom: 4, 
      basemap: 'gray' 
     }); 

     layer = new w.FeatureLayer(CROPS_URL, { 
      outFields: ['STATE', 'COUNTY', 'M086_07', 'AREA'], 
      infoTemplate: new w.InfoTemplate('${COUNTY}, ${STATE}', '<div style="font: 18px Segoe UI">The percentage of the area of the county that represents farmland is <b>${M086_07}%</b>.</div>') 
     }); 
     layer.setDefinitionExpression('AREA>0.01 and M086_07>0'); 


     markerSym = new w.SimpleMarkerSymbol(); 
     markerSym.setColor(greenFill); 
     markerSym.setOutline(markerSym.outline.setColor(greenOutline)); 
     renderer1 = new w.SimpleRenderer(markerSym); 
     renderer1.setProportionalSymbolInfo({ 
      field: 'M086_07', 
      minSize: 1, 
      maxSize: 10, 
      minDataValue: 0, 
      maxDataValue: 100 
     }); 

     //for the second renderer increase the dot sizes and set a backgroundFillSymbol 
     renderer2 = new w.SimpleRenderer(markerSym); 
     renderer2.setProportionalSymbolInfo({ 
      field: 'M086_07', 
      minSize: 5, 
      maxSize: 15, 
      minDataValue: 0, 
      maxDataValue: 100 
     }); 

     layer.setRenderer(new w.ScaleDependentRenderer({ 
      rendererInfos: [{ 
       'renderer': renderer1, 
        'minScale': 50000000, 
        'maxScale': 10000000 
      }, { 
       'renderer': renderer2, 
        'minScale': 0, 
        'maxScale': 5000000 
      }] 
     })); 

     $scope.map.addLayer(layer); 
    }); 

yukarıdaki kodu gösteren çalışma keman değiştirilmiş bir versiyonu, senin çözüm gibi ama küçük bir sorun var burada http://jsfiddle.net/technicolorenvy/2Ke62/4/

+0

bulundu olduğunu. Açısal çeviriyi kullanıyorum ve init.js'yi "//js.arcgis.com/3.14" adresinden yüklemek için bölünmüş bir saniye sürüyor ve açısal çevirmenin oluşturulmuş metin yerine {{'bir şey' | çeviri}} olarak görünmesine neden oluyor 'gereksinim' yüklemek için init.js yüklenene kadar. İstek hizmetinin içinde bağımlılık gereksinimini ortadan kaldırmanın bir yolunu biliyor musunuz? – laitha0

+0

Bunu önyükleyici veya 'veri yüklü' bayraklarıyla UI'nizde ele alırdım. Sorunun ve olası çözümün oldukça iyi bir açıklaması http://www.code-hound.com/add-a-preloader-to-your-website-using-angularjs/ – technicolorenvy

+0

Teşekkürler, bunu deneyeceğim. – laitha0

7

Haritanızı bir yönerge öğesi içinde oluşturmaya çalışıyorsunuz gibi görünüyor. Bu meşru bir kullanımdır, ancak Dojo'nun AMD yükleyicisini modüllerinizi yüklemek için kullandığınızdan emin olursunuz ve tüm Dojo iyiliği hazır olduktan sonra bootstrap Açısal uygulamanızı kullanırsınız.

Kısa bir süre önce Angular/Esri devresi üzerine bir yazım hazırladım ve örnek bir proje için kaynak kodu here bulunabilir.

Gerçekte yaptığım şey, bir Denetleyiciden haritayı oluşturmaktır, ancak işlem, yönergede oluşturmaya benzer olmalıdır.

define([ 
    'angular', 
    'esri/map' 
], function(angular, Map) { 
    function mapConfigs() { 
     return { 
      basemap: 'streets', 
      center: [-118.1704035141802,34.03597014510993], 
      zoom: 15 
     }; 
    } 
    function mapGen(elem) { 
     return new Map(elem, mapConfigs()); 
    } 
    function AppController($scope) { 
     $scope.map = mapGen('map'); 
    } 
    function init(App) { 
     App.controller('AppCtrl', ['$scope', AppController]); 
     return AppController; 
    } 
    return { start: init }; 
}); 

Ben Açısal uygulamayı işe koşulması önce Esri/Dojo bitlerini kullanarak tüm Açısal bit inşa etmek için bir önyükleme modülü kullanmak.

define([ 
    'angular', 
    'controllers/AppController', 
    'widgets/search/SearchBootstrap' 
], function(angular, AppController, SearchBootstrap) { 
    function init() { 
     var App = angular.module('app', ['ui.bootstrap']); 
     AppController.start(App); 
     SearchBootstrap.start(App); 
     // need to bootstrap angular since we wait for dojo/DOM to load 
     angular.bootstrap(document.body, ['app']); 
     return App; 
    } 
    return { start: init }; 
}); 

Bu biraz yardımcı olur umarım.