12

Próbuję dołączyć do kontrolera bibliotekę funkcji przechowywanych w fabryce. podobne do pytań takich jak to: Creating common controller functions

Moja główny sterownik wygląda następująco:

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(); */ 
} 

Następnie w innym pliku .js, mam stworzył fabrykę groceryInterface. Wprowadziłem tę fabrykę do kontrolera powyżej.

Fabryka

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; 
}); 

Ale w moim konsoli Wciąż dostaję ReferenceError: $scope is not defined at Object.factory.addToList itp Oczywiście zgaduję to ma wspólnego z tym, że używam $scope w moich funkcji w fabryka. Jak rozwiązać ten problem? Zauważam, że w wielu innych przykładach, na które patrzyłem, nikt nie używa $scope w swoich zewnętrznych funkcjach fabrycznych. Próbowałem wstrzykiwać $scope jako parametr w mojej fabryce, ale to zwykłe wyjście nie działa. (np. recipeApp.factory('groceryInterface', function(){)

Każda pomoc jest naprawdę doceniana!

Odpowiedz

25

Twoja fabryka nie może uzyskać dostępu do twojego $scope, ponieważ nie znajduje się w tym samym zakresie.

Spróbuj to zamiast:

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(); 
    } 
}); 

Alternatywnie, można spróbować użyć bardziej obiektowe podejście:

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łodko, dziękuję. Spróbuję tego! – LazerSharks

+2

@Gnuey - Zwróć uwagę, że 'bind' nie jest dostępny w starszych wersjach IE. Jeśli musisz je wspierać i chcesz użyć pierwszej metody, użyj [tego polifill MDN] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind# Kompatybilność) lub - jeśli masz jQuery na stronie - użyj zamiast tego ['$ .proxy'] (http://api.jquery.com/jQuery.proxy/). –

+1

Dobra, świetnie. To naprawdę bardzo pomocne informacje - mój szef dept i odwiedzający witrynę używają starszych wersji IE czasami z jakiegoś powodu: \ Czy zamiast tego napiszę '$ scope.addToList = $ .proxy (groceryInterface.addToList, $ scope)'? – LazerSharks

4

Nie można używać $scope w fabryce, gdyż nie jest zdefiniowana. Zamiast tego w funkcjach fabrycznych zmieniają się właściwości przedmiotu, który powraca fabryka, np.

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

te będą następnie przejdzie na Twoim $scope zmienna

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

Dzięki, spróbuję tego! – LazerSharks

+1

Edytowałem twoje rozwiązanie tak, że zamiast '$ scope.addToList = groceryInterface.addToList();', to czyta '$ scope.addToList = groceryInterface.addToList;' Odkryłem, że nawias na końcu 'addTotList()' był jednym wielkim problemem podczas mojego procesu debugowania ... dostałem całkiem fajny, odświeżający slap składni javascript ... – LazerSharks

3

To nie jest dokładna odpowiedź na to pytanie, ale miałem podobne problemy, że rozwiązane po prostu przechodzącej $ zakresie jak argument do funkcji w mojej fabryce. Więc nie będzie to normalny zakres $, ale zasięg $ w momencie wywołania funkcji w fabryce.

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 .. i sposób przekazania params do funkcji fabrycznych – HoosierCoder

Powiązane problemy