简体   繁体   中英

Use $rootScope to returns json in AngularJS ?

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 (ie 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM