5

Utworzono prostą aplikację testową rozstrzygania JS $ routeProvider. Daje następujący błąd:

Error: Unknown provider: dataProvider <- data 

Byłbym wdzięczny, gdyby ktoś mógł zidentyfikować, gdzie popełniłem błąd.

index.html

<!DOCTYPE html> 
<html ng-app="ResolveTest"> 
    <head> 
    <title>Resolve Test</title> 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js"> </script> 
    <script src="ResolveTest.js"></script> 
    </head> 
    <body ng-controller="ResolveCtrl"> 
    <div ng-view></div> 
    </body> 
</html> 

ResolveTest.js

var rt = angular.module("ResolveTest",[]); 

rt.config(["$routeProvider",function($routeProvider) 
{ 
    $routeProvider.when("/",{ 
    templateUrl: "rt.html", 
    controller: "ResolveCtrl", 
    resolve: { 
     data: ["$q","$timeout",function($q,$timeout) 
     { 
     var deferred = $q.defer(); 

     $timeout(function() 
     { 
      deferred.resolve("my data value"); 
     },2000); 

     return deferred.promise; 
     }] 
    } 
    }); 
}]); 

rt.controller("ResolveCtrl",["$scope","data",function($scope,data) 
{ 
    console.log("data : " + data); 
    $scope.data = data; 
}]); 

rt.html

<span>{{data}}</span> 

Odpowiedz

12

Problemem jest to, że masz ng-controller="ResolveCtrl" na tagu ciała w index.html gdy również w twoim $ routeProvider określasz ten sam kontroler dla rt.html. Wyjmij definicję kontrolera ze znacznika body i pozwól, aby $ routeProvider zajął się tym. Po tym działa świetnie.

+0

Nie zgadzam się. Zobacz http://jsfiddle.net/UbQHx/ – robbymurphy

+0

Dzięki jbw91, działa zgodnie z oczekiwaniami. – Hilo

+1

robbymurphy - nie masz rozwiązania ani wtrysku wyniku w skrzypce, więc nie powtarzasz poprawnie problemu. – Hilo

0

Dodając dane do definicji kontrolera, mówisz kątowo, że spodziewasz się wprowadzić usługę lub fabrykę tutaj, ale nie masz usługi danych lub fabryki, a więc błąd. Aby użyć zmiennej danych, masz wszystko, czego potrzebujesz od linii $scope.data. Aby to naprawić, musisz usunąć wtrysk danych z połączenia kontrolera.

var rt = angular.module("ResolveTest",[]); 

rt.config(["$routeProvider",function($routeProvider) 
{ 
    $routeProvider.when("/",{ 
    templateUrl: "rt.html", 
    controller: "ResolveCtrl", 
    resolve: { 
     data: ["$q","$timeout",function($q,$timeout) 
     { 
     var deferred = $q.defer(); 

     $timeout(function() 
     { 
      deferred.resolve("my data value"); 
     },2000); 

     return deferred.promise; 
     }] 
    } 
    }); 
}]); 

rt.controller("ResolveCtrl",["$scope", function($scope) 
{ 
    $scope.data = ""; 
}]); 

Jeśli chcesz mieć dostawcę danych fabrycznych dodać coś takiego

rt.factory('data', ['$http', function($http){ 
return { 
    // Functions to get data here 
} 
}]); 

potem rozmowy kontrolera odpowiednią funkcję z tej fabryki.

Również inni podkreślili, że nie potrzebujesz kontrolera zarówno na trasie, jak iw kontrolerze ng (to zagnieździć kontroler w kontrolerze, jeśli sprawdzasz zakresy).

Jeśli musisz użyć rozwiązania, nadal potrzebujesz fabryki, ponieważ jej rozstrzygnięcie wskaże tylko właściwą fabrykę, która musi zostać zadeklarowana osobno.

+2

Jeśli resolve jest funkcją, która zwraca obietnicę, zostaje rozwiązana, a następnie zostaje wprowadzona do kontrolera. – Hilo

0

Zgodnie z angularjs documentation for $routeprovider obiektem rozstrzygnięcia jest mapa z klucza (nazwa zależności) do funkcji fabrycznej lub nazwa istniejącej usługi. Spróbuj zamiast tego:

var myFactory = function($q, $timeout) { ... }; 
myFactory.$inject = ['$q', '$timeout']; 

$routeProvider.when("/",{ 
    templateUrl: "rt.html", 
    controller: "ResolveCtrl", 
    resolve: { 
     data: myFactory 
    } 
}); 
+1

Z dokumentu AngularJS $ routeProvider do rozstrzygnięcia: factory - {string | function}: Jeśli string, to jest to alias dla usługi. W przeciwnym razie, jeśli funkcja, to jest wstrzykiwany, a wartość zwracana jest traktowana jako zależność. Jeśli wynik jest obietnicą, zostaje rozwiązany, zanim jego wartość zostanie wprowadzona do kontrolera. – Hilo