【问题标题】:angularjs directive communicationangularjs指令通信
【发布时间】:2014-01-30 23:55:54
【问题描述】:

我是 angularjs 的新手,我一直在阅读大量文档并阅读各种文章和教程以及视频来帮助我弄清楚这些东西。 我正在尝试获取两个指令来在它们之间交换信息。我正在尝试做的一个真正简化的版本是在 odetocode (http://odetocode.com/blogs/scott/archive/2013/09/11/moving-data-in-an-angularjs-directive.aspx) 中,k scott allen 用一个具有 ng-controller 属性的 div 包装了他的指令,它工作得很好。

我正在处理一个稍微复杂一点的测试,我正试图让它与我提到的代码类似地工作。

当我在每个指令的实际模板中列出 ng-controller 属性时,我的两个指令会相互通信。它有效,但我认为它不正确。实际的控制器代码运行两次,每个指令运行一次。 当我将控制器移动到包装两个指令的 div 中时,两个指令停止交互(位置选择器模板中的更改事件不会更改控制器中的公园)。我很确定这与范围有关。如果有人能指出我正确的方向,或者我应该在哪里寻找信息,那将不胜感激。

这是我的小提琴显示我的代码http://jsfiddle.net/jgbL9/25/

<div ng-app="myApp">
    <location-selector ></location-selector ><br/>
    <portal-map ></portal-map >
</div>


    var App = angular.module('myApp', ['ngResource']);

    App.directive('locationSelector',['parkList', function(parkList) {
      return {
        restrict: 'E',
        scope: {
          parkId : '=',
          parkName : '='
        },
        template: '<select ng-controller="portalMapCtrl"'+
             ' ng-model="listParks" ng-change="changePark()" '+
             ' park-id="parkId" park-name="parkName" ' +
             ' ng-options="park as park.attributes.NAME for park in Parks" >'+
             '</select>',
        link: function (scope,element,attrs){
          parkList.getListFromGIS().success(function(data) {
            scope.Parks = data.features;
          });
        }
      };
    }]);

    App.directive('portalMap', function(){
      return {
        restrict: 'E',
        scope:{
          parkId: "=",
          parkName: "="
        },
        template: '<style type="text/css" media="screen">'+
            '#mapCanvas {height: 500px; width:75%; border:thin black solid; }'+
            '</style>'+
            '<div id="mapCanvas" park-id="parkId" park-name="parkName"  ng-controller="portalMapCtrl" ></div>'
      }
    });


    App.controller('portalMapCtrl',['$scope','parkList', function( $scope, parkList ){
      var map = {};
      var STREETMAPSERVICE = "https://gis.odot.state.or.us/ArcGIS/rest/services/BASEMAPS/Basemap_Streets/MapServer";
      var FOTOSSERVICE = "https://maps.prd.state.or.us/arcgis/rest/services/ESRI_TEST/MapServer?f=jsapi";
      var UTILSSERVICE = "http://gis.prd.state.or.us/ArcGIS/rest/services/OPRDAssets/MapServer";
      var UTILSSERVICE_PARKLAYER = 0;
      var UTILSSERVICE_STRUCTUREPOLY = 7;
      var UTILSSERVICE_SURFACE = 11;
      var UTILSSERVICE_PARCELS = 12;
      var timer;
      var ALL_LAYERS = [UTILSSERVICE_PARKLAYER,UTILSSERVICE_STRUCTUREPOLY,UTILSSERVICE_SURFACE,UTILSSERVICE_PARCELS];
      $scope.parkId = 0;
      $scope.parkName = "";
      $scope.changePark = function (){
        require(["esri/SpatialReference","esri/geometry/Polygon"],
          function(SpatialReference,Polygon){
            console.log('change park');
            $scope.parkId = $scope.listParks.attributes.PARK_HUB_ID;
            $scope.parkName = $scope.listParks.attributes.NAME;
            parkList.getParkFromGIS($scope.parkId).then(function(data){
               var x = data.data;
               var y = x.features[0];
               var rings = y['geometry'];
               var poly = new Polygon(rings);
               var xtnt = poly.getExtent();
               var sr = new SpatialReference({wkid:2992});
               xtnt.setSpatialReference (sr);
               map.setExtent(xtnt,true);
            });
          });
         };
       function addService(srvc, srvcType, lyrId){require([
               "esri/layers/ArcGISTiledMapServiceLayer",
                "esri/layers/ArcGISDynamicMapServiceLayer",
                "esri/layers/ImageParameters"], function(Tiled,Dynamic,Parameters){
           var mapService = {};

           if(srvcType == 'Tiled'){
             mapService = new Tiled(srvc);
           }else{
             var imageParameters = new Parameters();
             imageParameters.layerIds = lyrId;
             imageParameters.transparent = true;
             mapService = new Dynamic(srvc,{"imageParameters":imageParameters});
           }
           map.addLayer(mapService);
          });
        }

      function createMap(){
        require(["esri/map"],function(Map){
          console.log('create map');
          map = new Map("mapCanvas");
          addService(STREETMAPSERVICE,'Tiled');
          addService(FOTOSSERVICE,'Tiled');
          addService(UTILSSERVICE,'Dynamic',ALL_LAYERS);
        });
      }
      createMap();

   }]);


   App.factory('parkList',['$http', function($http) {
     return {
       getListFromGIS: function() {
         var myUrl = 'http://maps.prd.state.or.us/arcgis/rest/services/ESRI_TEST/MapServer/0/query?where=OBJECTID+%3E+0&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelIntersects&outFields=PARK_HUB_ID%2CNAME&returnGeometry=false&&returnIdsOnly=false&returnCountOnly=false&orderByFields=NAME&returnZ=false&returnM=false&returnDistinctValues=true&f=pjson&callback=JSON_CALLBACK';
         return $http ({ url: myUrl, method: 'JSONP'});
        },
        getParkFromGIS: function (id){
          var myUrl = "http://maps.prd.state.or.us/arcgis/rest/services/ESRI_TEST/MapServer/0/query?where=PARK_HUB_ID%3d"+id+"&f=pjson&callback=JSON_CALLBACK";
          return $http ({ url: myUrl, method: 'JSONP'});
        },
        JSON_CALLBACK: function(data) {}
     };
    }]);

(这是与每个指令模板中列出的 ng-controller 一起使用的代码)。

您想提供的关于我的代码结构或代码选择的任何其他 cmet 或建议也将不胜感激,正如我所提到的,我正在学习,我学得越多,我编码的乐趣就越大。

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-controller


    【解决方案1】:

    我相信由于指令中的隔离范围(链接函数中的 scope: { }),您遇到了问题。

    我建议将模板内联到您的应用程序中,而不是尝试将它们设为指令。

    特别是,locationSelector 将很难制定指令 - 通常更容易让您的输入元素成为其控制器所在元素的一部分。

    如果您确实想让它们成为指令,我建议将 listParts 值传递给 changePark 函数:

    <select ... ng-change="changePark(listParks)" ...>
    

    【讨论】:

    • 是的,这是我指令中的隔离范围。呵呵。我显然还有更多的阅读要做。从选择器的指令+链接中删除范围并将数据加载添加到控制器后,它运行良好。非常感谢您的帮助。
    猜你喜欢
    • 2014-10-06
    • 1970-01-01
    • 2016-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多