web-dev-qa-db-fra.com

Angularjs passant objet à directive

Débutant angulaire ici. J'essaie de comprendre ce qui ne va pas en passant des objets à des directives.

voici ma directive:

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

et voici le modèle où j'appelle la directive:

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

store.walks est un tableau d'objets.

Lorsque je lance ceci, scope.walks enregistre en tant que undefined tandis que scope se connecte correctement en tant que Scope et a même un enfant walks avec toutes les données que je recherche.

Je ne suis pas sûr de ce que je fais mal ici parce que cette méthode exacte a déjà fonctionné pour moi.

MODIFIER:

J'ai créé un plunker avec tout le code requis: http://plnkr.co/edit/uJCxrG

Comme vous pouvez le constater, le {{walks}} est disponible dans l'étendue, mais je dois y accéder via la fonction de liaison où il est toujours enregistré comme non défini. 

29
winkerVSbecks

Puisque vous utilisez $resource pour obtenir vos données, la fonction de liaison de la directive est en cours d'exécution avant que les données ne soient disponibles (car les résultats de $resource sont asynchrones), de sorte que la première fois dans la fonction de liaison scope.walks sera vide/indéfinie. Puisque votre modèle de directive contient {{}}s, Angular configure un $watch sur walks. Ainsi, lorsque $resource remplit les données, les déclencheurs $watch et l'affichage sont mis à jour. Cela explique également pourquoi vous voyez les données de parcours dans la console: lorsque vous cliquez sur le lien pour développer l'étendue, les données sont renseignées.

Pour résoudre votre problème, dans votre fonction de liaison $watch pour savoir quand les données sont disponibles:

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

Dans votre code de production, veillez simplement à ce qu'il ne soit pas défini:

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

Mise à jour: / Si vous utilisez une version de Angular dans laquelle $resource prend en charge les promesses, voir aussi la réponse de @ sawe.

40
Mark Rajcok

vous pouvez aussi utiliser 

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

Une autre solution serait d’ajouter ControllerAs à la directive par laquelle vous pouvez accéder aux variables de la directive.

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

Et ensuite, à votre avis, transmettez la variable à l'aide de la variable controllerAs.

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

Essayer: 

<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));
    }
  }
});
2
Elise Chant

votre $ scope.store déclaré n'est pas visible depuis le contrôleur ... vous le déclarez à l'intérieur d'une fonction ... pour qu'il ne soit visible que dans le cadre de cette fonction, vous devez déclarer ceci en dehors

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