在Promise解决之前正在呈现指令

IT技术 javascript angularjs angularjs-directive
2021-02-23 17:10:21

只有在我的Promise得到解决后,我才能让我的指令呈现其内容。我以为then()应该这样做,但它似乎不起作用..

这是我的控制器:

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

我的指令:

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

范围返回正常,当我在开发工具中检查它时scope.product不是未定义的,但是我认为这是因为当我检查它时,Promise已经解决了?

console.log(scope.product) 然而,返回未定义..

4个回答

正如有关此问题的官方线程中所述(很快关闭,因为“不会修复,因为它会使指令等待”),一种解决方法是将您的指令包装在ng-if

<div ng-if="myPromiseParam">
  <my-directive param="myPromiseParam">
</div>
啊,解决问题要容易得多
2021-04-30 17:10:21
为了性能,如果您知道它不会改变,请不要忘记使用一次绑定语法 (ng-if="::myPromiseParam")。
2021-05-02 17:10:21
这应该被接受,而不是使用被接受的使用手表。
2021-05-12 17:10:21

因为您的值是异步填充的,所以您需要添加一个监视函数来更新您的绑定元素。

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

您还可以将很多复杂性转移到指令控制器中,并使用链接函数仅操作 DOM。

true以第三个参数$watch引起了深刻的手表,因为你这种绑定指令的典范。

这里有几个带有很好例子的链接:
http : //www.ng-newsletter.com/posts/directives.html
http://seanhess.github.io/2013/10/14/angularjs-directive-design.html

我不明白你的问题。指令都只是控制器范围内的嵌套范围。如果你没有明确定义一个范围,angular 会创建一个。它还在后台为你创建手表(就像你做的那样{{project.name}}),所以我会说手表是最有角度的方式。此外,使用 AngularJS 掌握 Web 应用程序开发 | Packt Publishing是一本好书。
2021-05-15 17:10:21
谢谢吉姆,这是否意味着它只是没有更新的隔离范围?使用手表确实让我想到了,但我没有在网上看到任何例子,所以我认为这不是“角度方式”......希望不是这种情况,会试一试并报告。
2021-05-18 17:10:21
如果有人过来。$watch 也可以在父控制器中。由于指令绑定到相同的范围值。此外,如果您在一个对象上有一个手表,该对象获得了一个新的对象点符号值,那么您应该检查它是否也存在于手表中。
2021-05-18 17:10:21

我知道这是一个较旧的问题,但我想我会尝试提供更新的答案。

使用路由器时,ui-router 和 ngRouter 都有解析方法,可以在切换到该路由并在页面上呈现内容之前解析 url 更改的Promise。

ngRouter Resolve 教程
ui-router Resolve 文档

另一种选择$watch是使用 angulars $qpromise library而不是使用更具体地说,$q.when()方法。这需要Promise和价​​值观。如果它是一个Promise,它会.then()在Promise解决时触发如果它是一个值,它会将它包装在一个Promise中并立即解决它。

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

或者有几种方法你不能只用 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>    

在指令中对变量使用 $watch 以获取变量的更新值。

您还可以使用 $q 来解决Promise。