Вопрос

I have this function which returns json with $scope.product_owners = data

$http({
    url: "php/functions.php",
    method: "GET",
    params: { 
        action: "get_product_owners"
    }
}).success(function(data) {
    $scope.product_owners = data;
});  

Currently, I'm calling this function in all my controllers because it is used in them, but I'm wondering if it was possible to call once. For example, with the $rootScope or something like that.

Это было полезно?

Решение

The "Angular way" for sharing data across controllers is to use a service:

app.factory('ProductOwners', function ($http) {
    var service = {
        data: []
    };

    $http({
        url: "php/functions.php",
        method: "GET",
        params: { 
            action: "get_product_owners"
        }
    }).success(function(data) {
        service.data = data;
    });

    return service;
});

Then inject the service in every controller:

app.controller('someCtrl', function (ProductOwners) {
    $scope.product_owners = ProductOwners.data;
});

A different implementation with "lazy" evaluation (i.e. it only makes the call if it is needed and then serves the same data):

app.factory('ProductOwners', function ($http, $q) {
    var data;

    function getDataIfNeeded() {
        if (data !== undefined) {
            return $q.when(data);
        }

        return $http({
            url: "php/functions.php",
            method: "GET",
            params: { 
                action: "get_product_owners"
            }
        }).then(function(response) {
            data = response.data;
            return data;
        });
    }

    return {
        getData: getDataIfNeeded
    };
});

app.controller('someCtrl', function (ProductOwners) {
    ProductOwners.getData().then(function (data) {
        $scope.product_owners = data;
    });
});

UPDATE

Yet another different implementation with "lazy" evaluation and supporting an argument passed to getData():

app.factory('GenericService', function ($http, $q) {
    var data = {};

    function getDataIfNeeded(action) {
        action = action || 'default';

        if (data[action] !== undefined) {
            return $q.when(data[action]);
        }

        return $http({
            url: "php/functions.php",
            method: "GET",
            params: { 
                action: action
            }
        }).then(function(response) {
            data[action] = response.data;
            return data[action];
        });
    }

    return {
        getData: getDataIfNeeded
    };
});

app.controller('someCtrl', function (GenericService) {
    GenericService.getData("get_product_owners").then(function (data) {
        $scope.product_owners = data;
    });
});

Другие советы

If the same code is used by several controllers in your application, you may wish to put it inside a service and then you can call it from the controllers:

myApp.service('products', function($http) {
    this.getProductOwners = function(targetScope) {
        $http({
            url: "php/functions.php",
            method: "GET",
            params: { 
                action: "get_product_owners"
            }
        }).success(function(data) {
            targetScope.product_owners = data;
        });  
    };
});

And then, in your controllers:

myApp.controller('MyCtrl', function($scope, products) {
    products.getProductOwners($scope);
});

Using services is the preferred way for code reuse between several controllers.

1- you can make a factory and then call it when needed inside controllers

yourApp.factory('httpFactory', function($http) {
return {
$http({
    url: "php/functions.php",
    method: "GET",
    params: { 
        action: "get_product_owners"
    }
}).success(function(data) {
    this.product_owners = data;
}); 
}}

then basically you inject it in to wherever,

yourApp.controller('xCtrl', function (httpFactory) {
    $scope.product_owners = httpFactory.product_owners;
});

2- you can also have a main controller for the app like this

<body ng-controller="mainCtrl">

and then put your code in that

yourApp.controller('mainCtrl', function($scope, $http) {
$http({
    url: "php/functions.php",
    method: "GET",
    params: { 
        action: "get_product_owners"
    }
}).success(function(data) {
    $scope.product_owners = data;
}); }

now you can access this data from any schild scope

You can definitely place it on the $rootScope to save multiple calls.

Question is - if you place the one call on one controller, is it possible to go to a different view/controller and thus skipping the call ?

If the answer is no then you have no problem.

If the answer is yes then you should have a controller wrapping all the other ones to make sure you have that data.

Another possibility is have a service to keep the product_owners data, and each controller can access that server to get the data, and if it's not available, get it by the ajax request.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top