Angularjs将对象传递给指令

时间:2013-01-31 06:39:35

标签: angularjs angularjs-directive

Angular新手在这里。我试图找出将对象传递给指令时出了什么问题。

这是我的指示:

app.directive('walkmap', function() { 
  return {
    restrict: 'A',
    transclude: true,
    scope: { walks: '=walkmap' },
    template: '<div id="map_canvas"></div>',
    link: function(scope, element, attrs)
    {
      console.log(scope);
      console.log(scope.walks);
    }
  };
});

这是我调用指令的模板:

<div walkmap="store.walks"></div>

store.walks是一个对象数组。

当我运行此时,scope.walks记录为undefined,而scope作为范围记录正常,甚至还有一个walks子项,其中包含我要查找的所有数据

我不确定我在这里做错了什么,因为这个确切的方法以前对我有效。

编辑:

我创建了一个包含所有必需代码的plunker:http://plnkr.co/edit/uJCxrG

正如您所看到的,{{walks}}在范围内可用,但我需要在链接功能中访问它,它仍然以未定义的方式记录。

5 个答案:

答案 0 :(得分:40)

由于您使用$resource来获取数据,因此指令的链接函数在数据可用之前运行(因为$resource的结果是异步的),所以第一次在链接函数中scope.walks将为空/未定义。由于您的指令模板包含{{}},因此Angular会在$watch上设置walks,因此当$resource填充数据时,$watch触发器和显示更新。这也解释了为什么您在控制台中看到散步数据 - 当您单击链接以扩展范围时,将填充数据。

要解决您的问题,请在链接功能$watch中了解数据何时可用:

scope.$watch('walks', function(walks) {
   console.log(scope.walks, walks);
})

在您的生产代码中,只需防止它未定义:

scope.$watch('walks', function(walks) {
  if(walks) { ... }
})

更新:如果您使用的是$resource支持承诺的Angular版本,请参阅@ sawe的回答。

答案 1 :(得分:11)

您也可以使用

scope.walks.$promise.then(function(walks) {
    if(walks) {
      console.log(walks);
    }
  });

答案 2 :(得分:3)

另一个解决方案是将ControllerAs添加到指令中,通过该指令可以访问指令的变量。

app.directive('walkmap', function() { 
  return {
    restrict: 'A',
    transclude: true,
    controllerAs: 'dir',
    scope: { walks: '=walkmap' },
    template: '<div id="map_canvas"></div>',
    link: function(scope, element, attrs)
    {
      console.log(scope);
      console.log(scope.walks);
    }
  };
});

然后,在您的视图中,使用controllerAs变量传递变量。

<div walkmap="store.walks" ng-init="dir.store.walks"></div>

答案 3 :(得分:2)

尝试:

<div walk-map="{{store.walks}}"></div>

angular.module('app').directive('walkMap', function($parse) {
  return {
    link: function(scope, el, attrs) {
      console.log($parse(attrs.walkMap)(scope));
    }
  }
});

答案 4 :(得分:0)

你声明的$ scope.store在控制器中是不可见的..你在一个函数中声明它。所以它只在该函数的范围内可见,你需要在外面声明:

app.controller('MainCtrl', function($scope, $resource, ClientData) {
  $scope.store=[];         // <- declared in the "javascript" controller scope
  ClientData.get({}, function(clientData) {
  self.original = clientData;
  $scope.clientData = new ClientData(self.original);
  var storeToGet = "150-001 KT";
  angular.forEach(clientData.stores, function(store){
   if(store.name == storeToGet ) {
     $scope.store = store;      //declared here it's only visible inside the forEach
     }
   });
  });
 });