web-dev-qa-db-fra.com

La directive est rendue avant que la promesse soit résolue

Je ne parviens pas à faire en sorte que ma directive ne rende le contenu que lorsque ma promesse a été résolue. Je pensais que then() était censé le faire, mais cela ne semble pas fonctionner.

Voici mon contrôleur:

// Generated by CoffeeScript 1.6.3
(function() {
  var sprangularControllers;

  sprangularControllers = angular.module('sprangularControllers', ['sprangularServices', 'ngRoute']);

  sprangularControllers.controller('productsController', [
    '$scope', '$route', '$routeParams', 'Product', 'Taxonomy', function($scope, $route, $routeParams, Product, Taxonomy) {
      Taxonomy.taxonomies_with_meta().$promise.then(function(response) {
        return $scope.taxonomies = response.taxonomies;
      });
      return Product.find($routeParams.id).$promise.then(function(response) {
        return $scope.currentProduct = response;
      });
    }
  ]);

}).call(this);

Ma directive:

// Generated by CoffeeScript 1.6.3
(function() {
  var sprangularDirectives;

  sprangularDirectives = angular.module('sprangularDirectives', []);

  sprangularDirectives.directive('productDirective', function() {
    return {
      scope: {
        product: '='
      },
      templateUrl: 'partials/product/_product.html',
      link: function(scope, el, attrs) {
        console.log(scope);
        console.log(scope.product);
        return el.text(scope.product.name);
      }
    };
  });

}).call(this);

Le contenu de Scope est correct, et lorsque je le vérifie dans les outils de développement, scope.product N’est pas indéfini, mais je suppose que c’est parce qu’au moment de le vérifier, la promesse a été résolue?

console.log(scope.product) renvoie cependant indéfini ..

59
Melbourne2991

Comme votre valeur est renseignée de manière asynchrone, vous voudrez ajouter une fonction de surveillance qui met à jour votre élément lié.

  link: function(scope, el, attrs) {
    scope.$watch('product', function(newVal) {
        if(newVal) { el.text(scope.product.name);}
    }, true);
  }

Vous pouvez également déplacer beaucoup de complexité dans un contrôleur de directive et utiliser la fonction de liaison pour manipuler le DOM uniquement.

Le troisième paramètre true à $watch provoque une surveillance approfondie, car vous liez cette directive à un modèle.

Voici quelques liens avec de bons exemples:
http://www.ng-newsletter.com/posts/directives.html
http://seanhess.github.io/2013/10/14/angularjs-directive-design.html

43
Jim Schubert

Comme indiqué dans n fil officiel sur ce problème (rapidement fermé car "ne résoudra pas le problème, les directives attendraient"), une solution consiste à envelopper votre directive dans un ng-if:

<div ng-if="myPromiseParam">
  <my-directive param="myPromiseParam">
</div>
81
Javarome

Je sais que c’est une question plus ancienne, mais je pensais pouvoir essayer de vous fournir une réponse actualisée.

Lorsque vous utilisez un routeur, ui-router et ngRouter ont des méthodes de résolution qui résoudront les promesses relatives aux modifications d'URL avant de basculer sur cette route et d'afficher le contenu de la page.

tutoriel sur la résolution de ngRouter
Documents de résolution ui-router

Une autre option, au lieu d'utiliser $watch, Consiste à utiliser des angulaires bibliothèque de promesses $q . Plus spécifiquement, la méthode $q.when(). Cela prend des promesses et des valeurs. SI c'est une promesse, il déclenchera une .then() lorsque la promesse sera résolue. Si c'est une valeur, il l'enveloppe dans une promesse et la résout immédiatement.

link: function(scope, el, attrs){
    $q.when(scope.product).then(function(product){
        scope.product = product;
        el.text(scope.product.name);
    });
}

Ou bien, il n’est pas possible de montrer quoi que ce soit avec du HTML.

<product-directive product='object'>
    <!-- Will hide span until product.name exists -->
    <span ng-show='product.name'>{{ product.name }}</span> 

    <!-- Will show default text until key exists -->
    {{ product.name || 'Nothing to see here' }}

    <!-- Will show nothing until key exists -->
    <span ng-bind='product.name'></span>
</product-directive>    
24
migpok35

utilisez $ watch sur votre variable dans votre directive pour obtenir la valeur mise à jour de votre variable.

vous pouvez également utiliser $ q pour résoudre la promesse.

0
Hetal Sangoi