Подтвердить что ты не робот

Angularjs, передающий объект директиве

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 со всеми данными, которые я ищу.

Я не уверен, что я делаю неправильно здесь, потому что этот точный метод работал раньше для меня.

EDIT:

Я создал плункер со всем необходимым кодом: http://plnkr.co/edit/uJCxrG

Как вы видите, доступен в области видимости, но мне нужно получить доступ к ней в функции link, где она все еще регистрируется как undefined.

4b9b3361

Ответ 1

Так как вы используете $resource для получения ваших данных, функция ссылки указывается до того, как данные будут доступны (поскольку результаты из $resource являются асинхронными), поэтому первый раз в функции link scope.walks будет be empty/undefined. Поскольку ваш шаблон директивы содержит {{}} s, Angular устанавливает $watch на walks, поэтому, когда $resource заполняет данные, триггеры $watch и дисплей обновляются. Это также объясняет, почему вы видите данные ходьбы в консоли - к тому времени, когда вы нажмете ссылку, чтобы развернуть область, данные заселяются.

Чтобы решить вашу проблему, в вашей функции связи $watch узнать, когда доступны данные:

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

В вашем производственном коде просто предохраняйте его от undefined:

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

Обновление: Если вы используете версию Angular, где $resource поддерживает promises, см. также ответ @sawe.

Ответ 2

вы также можете использовать

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

Ответ 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>

Ответ 4

Попробуйте:

<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));
    }
  }
});

Ответ 5

ваш объявленный объект $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 only visible inside the forEach
     }
   });
  });
 });