12

Ich versuche, eine Bibliothek von Funktionen, die in einer Fabrik gehalten werden, in einen Controller zu integrieren. Ähnlich Fragen wie diese: Creating common controller functions

Mein Hauptcontroller wie folgt aussieht:

recipeApp.controller('recipeController', function ($scope, groceryInterface, ...){ 

$scope.groceryList = []; 
// ...etc...  

/* trying to retrieve the functions here */ 
$scope.groceryFunc = groceryInterface; // would call ng-click="groceryFunc.addToList()" in main view 
    /* Also tried this: 
    $scope.addToList = groceryInterface.addToList(); 
    $scope.clearList = groceryInterface.clearList(); 
    $scope.add = groceryInterface.add(); 
    $scope.addUp = groceryInterface.addUp(); */ 
} 

Dann habe ich die Fabrik groceryInterface erstellt, in einer anderen JS-Datei. Ich habe diese Fabrik in den Controller oben eingespritzt.

Fabrik

recipeApp.factory('groceryInterface', function(){ 

     var factory = {}; 

    factory.addToList = function(recipe){ 
     $scope.groceryList.push(recipe); 
        ... etc.... 
    } 

    factory.clearList = function() { 
      var last = $scope.prevIngredients.pop(); 
      .... etc... 
    } 

    factory.add = function() { 
    $scope.ingredientsList[0].amount = $scope.ingredientsList[0].amount + 5; 
    } 

    factory.addUp = function(){ 
     etc... 
    } 

    return factory; 
}); 

Aber in meiner Konsole halte ich ReferenceError: $scope is not defined at Object.factory.addToList bekommen usw. Offensichtlich in der ich vermute, dies mit der Tatsache zu tun hat, dass ich $scope in meinen Funktionen bin mit Fabrik. Wie kann ich das beheben? Ich bemerke, dass in vielen anderen Beispielen, die ich angeschaut habe, niemand jemals $scope innerhalb ihrer externen Fabrikfunktionen verwendet. Ich habe versucht, $scope als Parameter in meiner Fabrik zu injizieren, aber diese Ebene hat nicht funktioniert. (z.B. recipeApp.factory('groceryInterface', function(){)

Jede Hilfe wird wirklich geschätzt!

Antwort

25

Ihre Fabrik kann nicht auf Ihre $scope zugreifen, da sie nicht im selben Umfang liegt.

Versuchen Sie stattdessen:

recipeApp.controller('recipeController', function ($scope, groceryInterface) { 

    $scope.addToList = groceryInterface.addToList; 
    $scope.clearList = groceryInterface.clearList; 
    $scope.add  = groceryInterface.add; 
    $scope.addUp  = groceryInterface.addUp; 
} 

recipeApp.factory('groceryInterface', function() { 

    var factory = {}; 

    factory.addToList = function (recipe) { 
     this.groceryList.push(recipe); 
    } 

    factory.clearList = function() { 
     var last = this.prevIngredients.pop(); 
    } 
}); 

Alternativ können Sie versuchen, einen objektorientierten Ansatz:

recipeApp.controller('recipeController', function ($scope, groceryInterface) { 

    $scope.groceryFunc = new groceryInterface($scope); 
} 

recipeApp.factory('groceryInterface', function() { 

    function Factory ($scope) { 

     this.$scope = $scope; 
    } 

    Factory.prototype.addToList = function (recipe) { 
     this.$scope.groceryList.push(recipe); 
    } 

    Factory.prototype.clearList = function() { 
     var last = this.$scope.prevIngredients.pop(); 
    } 

    return Factory; 
}); 
+0

Süße, danke. Ich werde es ausprobieren! – LazerSharks

+2

@Gnuey - Beachten Sie, dass 'bind' in älteren Versionen von IE nicht verfügbar ist. Wenn Sie diese unterstützen müssen und die erste Methode verwenden möchten, verwenden Sie entweder [diesen MDN-Polyfill] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind# Kompatibilität) oder - wenn Sie jQuery auf der Seite haben - verwenden Sie stattdessen ['$ .proxy'] (http://api.jquery.com/jQuery.proxy/). –

+1

Okay, großartig. Das ist wirklich sehr hilfreiche Informationen - meine Deputy Head und Website-Besucher verwenden ältere IE-Versionen manchmal aus irgendeinem Grund: \ Würde ich stattdessen schreiben $ scope.addToList = $ .proxy (groceryInterface.addToList, $ Scope) '? – LazerSharks

4

Sie nicht $scope in einer Fabrik verwendet werden können, da es nicht definiert ist. Stattdessen ändern Sie in Ihren Factory-Funktionen die Eigenschaften des Objekts, das die Factory zurückgibt, z.

factory.addToList = function (recipe) { 
    this.groceryList.push(recipe); 
} 

diese werden dann auf Ihre $scope Variable weitergegeben bekommen

$scope.addToList = groceryInterface.addToList; 
// ... = groceryInterface.addToList(); would assign to `$scope.addToList` what is returned, instead of the function itself. 
+0

Danke, ich werde das ausprobieren! – LazerSharks

+1

Ich habe Ihre Lösung so bearbeitet, dass anstelle von $ scope.addToList = groceryInterface.addToList(); '' $ scope.addToList = groceryInterface.addToList; 'Ich habe die Klammer am Ende von' addTotList() 'gefunden war ein großes Problem während meiner Debug-Prozess ... habe mich ziemlich gut erfrischende Slap Javascript Syntax ... – LazerSharks

3

Dies ist für diese Frage nicht die genaue Antwort, aber ich hatte eine ähnliche Probleme, die ich als durch einfaches Durchleiten $ Umfang gelöst ein Argument für eine Funktion in meiner Fabrik. Es ist also nicht der normale $ scope, sondern $ scope zu dem Zeitpunkt, zu dem die Funktion in der Factory aufgerufen wird.

app.controller('AppController', function($scope, AppService) { 


    $scope.getList = function(){ 

    $scope.url = '/someurl' 

    // call to service to make rest api call to get data 

    AppService.getList($scope).then(function(res) { 
     // do some stuff 

    }); 
    } 

}); 


app.factory('AppService', function($http, $q){ 
    var AppService = { 

    getList: function($scope){ 
     return $http.get($scope.url).then(function(res){ 
     return res; 
     }); 
    }, 

    } 

    return AppService; 
}); 
+0

DRY AF .. und eine Möglichkeit, Params in Factory-Funktionen zu übergeben – HoosierCoder