2014-01-17 81 views
55

我在解决我的承诺后才能获取我的指令以呈现其内容。我以为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是不是未定义,但我认为是因为当我检查它的承诺已解决?

console.log(scope.product)然而,返回undefined ..

回答

43

因为你的价值是异步填充,你要添加监视功能,更新您的绑定元素。

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

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

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

这里有一对夫妇的良好范例链接:
http://www.ng-newsletter.com/posts/directives.html
http://seanhess.github.io/2013/10/14/angularjs-directive-design.html

+0

谢谢吉姆,这是否意味着它只是没有更新的隔离范围?使用手表确实困扰了我,但是我没有在网上看到任何例子,所以我推测这不是'有角度的方式'......希望事实并非如此,会给出一个结果并报告回来。 – Melbourne2991

+0

我不明白你的问题。指令都是控制器范围内的嵌套作用域。如果你没有明确定义一个范围,那么angular会创建一个。它也会在后台为你创建手表(比如当你做'{{project.name}}')时,所以我会说手表是最有角度的。另外,[掌握使用AngularJS进行Web应用程序开发| Packt Publishing](http://bit.ly/1deKEKU)是一本好书。 –

+1

如果有人来此。 $ watch也可以在父控制器中。由于该指令绑定到相同的范围值。此外,如果您在获取新对象点注释值的对象上有手表,那么您应该检查它是否存在于手表中。 – mjwrazor

24

我知道这是一个老问题,但想到我会尽我的手在提供更新的答案。

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

ngRouter Resolve tutorial
ui-router Resolve docs

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

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>  
75

正如an official thread about this issue规定(赶紧闭上为“不会解决,因为它将使等待指令”),一个解决方法是换你的指令在ng-if

<div ng-if="myPromiseParam"> 
    <my-directive param="myPromiseParam"> 
</div> 
+5

Ahhh sooo更容易修复问题 –

+4

为了提高性能,如果您知道它不会更改,请不要忘记使用绑定一次语法(ng-if =“:: myPromiseParam”)。 – Javarome

+2

这应该接受,而不是使用接受的使用手表。 –

0

使用$腕表在你的指令的变量上获取变量的更新值。

您还可以利用$ q来解决承诺。