Angular アプリのメイン コントローラーで $resource を使用して、サーバーから JSON オブジェクトを読み込もうとしています。データが表示されたり、ページ分割されたりする ng-view にパーシャルをロードするいくつかのルートがあります。
これで問題なく動作しますが、次の目標は、クリックされたリンクに基づいてデータをフィルタリングし、URL を更新して、ユーザーがそのフィルタリングされたデータ (domain.dev/products/brandname) にリンクできるようにすることです。
サイトがルート URL または製品へのルートを呼び出さないその他の URL から読み込まれる限り、すべて問題ありませんが、/products からサイトを読み込もうとするとすぐにデータが読み込まれないため、サイトが壊れます。ルートがパーシャルをビューにロードする前に使用できます。
約束がこの問題に役立つかどうか、もしそうなら、どこから始めればよいかを理解しようとしています。私は約束についていくつか読んでおり、それが答えだと確信していますが、既存のコードで動作させることができません。
$resource は見栄えが良いので使用していますが、オプションが多いため、ここではおそらく $http の方が適しているでしょう。
簡単に言えば、サイトが / から読み込まれるときは、JSON を使用するパーシャルがまだそこになく、それらが読み込まれるとデータの準備が整っているため、すべて問題ありません。しかし、パーシャルをロードするコントローラーがサイトのロード時に呼び出されると、データが存在せず、変数を設定しようとすると ProductController がエラーをスローします。$scope.products は存在しないため、長さの方法はありません。ng-show="products" を使用して div でラップされたパーシャルのコード全体がありますが、コントローラーでエラーがスローされているように見えるため、この場合は期待どおりに機能しません。パーシャルは引き続き読み込まれますが、{{ vars }} が表示されます。
これに関するガイダンスをいただければ幸いです。
編集: URL パラメーターをエンドポイントに送信しようとしているわけではありません。実際にはすべてのデータを前もって取得したいので、フィルターは Angular で行います。基本的には、/products/string がパスであるかどうかに関係なく、メイン アプリですべてのデータをダウンロードして (それほど多くはありません)、準備を整えておきたいと考えています。私の目標は、フィルターごとに HTTP 呼び出しを行わないようにすることです。私はそれを機能させましたが、HTTP結果を待っているいくつかのアイテムだけでは遅すぎました. 私の主な問題は、データを取得できることですが、サーバーからデータが返されるまでに、ProductController が実行され、エラーがスローされます。基本的に、実行しようとする前にコントローラーがデータを待機するようにします。
編集2:私は問題を理解しました.それは私が自分のアプリを構築しようとしていた方法です. コードを分離する最善の方法は、製品を独自のコントローラーに入れることだと思いましたが、事前にデータをロードしたいので、メインの appController でサービスを呼び出す必要があります。それは私の間違いでした。すべてのコードを appController に移動し、製品ルートのコントローラーを変更すると、期待どおりに機能しました。promise についてもっと学ぶように促されました。これは良いことであり、学んだことを利用することができました。フィルタリングの問題はまだありますが、これで問題は解決します。
この投稿から助けを得ました: AngularJS: 非同期呼び出しを待っています
作業コードは次のとおりです。
elite.controller('productController', function($scope, $routeParams, $rootScope, $location, Products){
$scope.brand = $routeParams.brand;
$rootScope.productPagination = function(){
$scope.currentPage = 1;
$scope.numPerPage = 10;
$scope.maxSize = 6;
$scope.totalItems = $rootScope.products.length;
$scope.numPages = Math.ceil($scope.totalItems / $scope.numPerPage);
$scope.$watch('currentPage + numPerPage', function() {
var begin = (($scope.currentPage - 1) * $scope.numPerPage)
, end = begin + $scope.numPerPage;
$scope.filteredProducts = $rootScope.products.slice(begin, end);
});
}
if (!$rootScope.products){
Products.getProducts().then(function(data){
$rootScope.products = data.products;
$rootScope.productPagination();
});
}else{
$rootScope.productPagination();
}
});
ここまでのアプリ (要約) は次のとおりです。
var elite = angular.module("elite", ["ngResource", "ngSanitize", "ui.bootstrap"]);
elite.config(['$routeProvider', function($routeProvider){
$routeProvider.when('/', {
templateUrl: 'partials/home.html',
controller: 'homeController'
})
$routeProvider.when('/products', {
templateUrl:'partials/products.html',
controller: 'productController'
})
$routeProvider.when('/products/:brand', {
templateUrl:'partials/products.html',
controller: 'productController'
})
$routeProvider.otherwise({redirectTo :'/'})
}]);
elite.factory('Products', function($resource){
return $resource("/products")
});
elite.controller('appController', function($scope, $location, $routeParams, Products){
Products.get({},function (data){
$scope.products = data.products;
});
});
elite.controller('productController', function($scope, $location, $routeParams, $resource){
$scope.brand = $routeParams.brand;
$scope.currentPage = 1;
$scope.numPerPage = 10;
$scope.maxSize = 6;
$scope.$watch($scope.products, function(){
$scope.numPages = Math.ceil($scope.products.length / $scope.numPerPage);
$scope.$watch('currentPage + numPerPage', function() {
var begin = (($scope.currentPage - 1) * $scope.numPerPage)
, end = begin + $scope.numPerPage;
$scope.totalItems = $scope.products.length;
$scope.filteredProducts = $scope.products.slice(begin, end);
});
});
});
<div ng-show="products">
<h2>{{ brand }} products...</h2>
<h4>{{products.length}} items</h4>
<pagination ng-show="numPages" total-items="totalItems" page="currentPage" max-size="maxSize" class="pagination-small" boundary-links="true" rotate="false" num-pages="numPages"></pagination>
<table class="table table-striped">
<tr ng-repeat="product in filteredProducts">
<td>{{product.brand}}</td>
<td>{{product.title}}</td>
<td ng-bind="product.priceDealer | currency"></td>
<td>{{product.msrp | currency}}<td>
</tr>
</table>
</div>