2014-01-17 307 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來解決承諾。