1

I have a factory called search.

I have many controllers called SearchCampaignController, SearchQuotaController and so on.

The factory search is a singleton object to which these controllers add function implementations to.

The problem is, a parent controller called SearchController must call a function inside the factory search which is not yet implemented because the child controllers execute after the parent controller executes.

It seems like I'm doing something wrong.

angular
    .module('app.search')
    .factory('search', search);

search.$inject = ['$http', '$window', '$state', 'CONF', '$mdToast', 'USER_ROLES', 'USER_MODULES'];

function search($http, $window, $state, CONF, $mdToast, USER_ROLES, USER_MODULES) {

    var searchInfo;

    function updateQueryString(params) {
        $state.go(

            'search',

            {
                searchType: params.searchType,
                quotaId: params.quotaId,
                campaignName: params.campaignName,
                templateName: params.templateName,
                passId: params.passId,
                certId: params.certId
            },

            {notify: false}

        )
    }

    function getQuotaById(params) {
        var reqPath = CONF.apiPath + 'core/quotas/' + params.quotaId;
        return $http.get(reqPath);
    }

    function getCampaignById(params) {
        var reqPath = CONF.apiPath + 'core/quotas/' + params.quotaId + '/campaigns/' + params.campaignName;
        return $http.get(reqPath);
    }

    function queryCampaigns(params) {
        var reqPath = CONF.apiPath + 'core/quotas/' + params.quotaId + '/campaigns';
        return $http.get(reqPath);
    }

    function getTemplateById(params) {
        var reqPath = CONF.apiPath + 'core/quotas/' + params.quotaId + '/campaigns/' + params.templateName;
        return $http.get(reqPath);
    }

    function queryTemplates(params) {
        var reqPath = CONF.apiPath + 'core/campaigns/' + params.campaignName + '/templates';
        return $http.get(reqPath);
    }

    function getPassById(params) {
        var reqPath = CONF.apiPath + 'core/passes/' + params.passId;
        return $http.get(reqPath);
    }

    function getPassbookById(params) {
        var reqPath = CONF.apiPath + 'core/passbookCert/' + params.certId;
        return $http.get(reqPath);
    }

    function queryPassbookCerts(params) {
        var reqPath = CONF.apiPath + 'core/quotas/' + params.quotaId + '/passbookCerts';
        return $http.get(reqPath);
    }

    //Global search logic
    //NEED TO RE-FACTOR
    function searchMasterFunction(params, obj) {

        if(params.searchType){
            search.changeSearchType(params.searchType);
        }

        updateQueryString(params);

        if(params.quotaId){
            search.getQuotaAndDisplayResult(params);
            // search.getPassbookCertsAndDisplayResult(params);

            search.updateQuotaIdInTemplateTab(params); //special - needs re-visit
        }

        if(params.quotaId && !params.campaignName){
            search.getCampaignsAndDisplayResult(params);
        }

        if(params.quotaId && params.campaignName && params.templateName){
            search.getCampaignAndDisplayResult(params);
            search.getTemplateAndDisplayResult(params);
        }else if(params.quotaId && params.campaignName){
            search.getCampaignAndDisplayResult(params);
            search.getTemplatesAndDisplayResult(params);
        }else if(params.quotaId && params.templateName){
            search.getTemplateAndDisplayResult(params);
        }

        if(params.campaignName){
            search.getTemplatesAndDisplayResult(params);
        }

        if(params.passId){
            search.getPassAndDisplayResult(params);
        }

        //getPassbookById

    }

    var search = {

        searchInfo: searchInfo,

        searchMasterFunction: searchMasterFunction,

        getQuotaById: getQuotaById,

        getCampaignById: getCampaignById,
        queryCampaigns: queryCampaigns,

        getTemplateById: getTemplateById,
        queryTemplates: queryTemplates,

        getPassById: getPassById,

        getPassbookById: getPassbookById,
        queryPassbookCerts: queryPassbookCerts
    };

    return search;


}

And this is my parent controller which should call the searchMasterFunction inside the factory search so that when there are values in the query string, it automatically populates any search results according to the logic inside the search factory.

angular
    .module('app.search')
    .controller('SearchController', SearchController);

SearchController.$inject = ['$state', 'search', '$scope', '$log'];

function SearchController($state, search, $scope, $log){

    $log.warn("Executing SearchController");

    var vm = this;

    vm.searchType = $state.params.searchType; //re-visit
    vm.tabs = ['quota', 'campaign', 'template', 'pass', 'cert'];

    vm.changeSearchTypeOnTabClick = changeSearchTypeOnTabClick;

    search.changeSearchType = changeSearchType;

    function changeSearchTypeOnTabClick(searchType) {
        $state.go('search', {searchType: searchType}, {notify: false});
    }

    function changeSearchType(searchType) {
        vm.searchType = searchType;
    }

    // this function call is what is causing the problem
    // search.searchMasterFunction($state.params);

}

The following is one of my child controllers which implement functions such as search.getQuotaAndDisplayResult.

angular .module('app.search') .controller('SearchQuotaController', SearchQuotaController);

SearchQuotaController.$inject = ['search', '$scope', '$log'];

function SearchQuotaController(search, $scope, $log){

    $log.info("Executing SearchQuotaController");

    var vm = this;

    vm.searchInfo;
    vm.quota;

    vm.searchBtnClick = searchBtnClick;

    search.getQuotaAndDisplayResult = getQuotaAndDisplayResult; //THIS LINE IS WHAT NEEDS ATTENTION. I'm adding a function into the `search` factory.

    function searchBtnClick(params){

        search.searchMasterFunction(params);

    };

    function getQuotaAndDisplayResult(params) {
        vm.searchInfo = params; //update fields in the Quota view

        search.getQuotaById(params).then(function(quota){
            vm.quota = quota.data; //update the quota object in the view
        });
    };

}

So the problem is that SearchQuotaController runs AFTER SearchController and therefore if I try to call search.searchMasterFunction in SearchController, it will not be able to execute properly since search.searchMasterFunction relies on the child controller to execute in order for the function implementation to be complete.

Any help would be greatly appreciated. I've already considered the $broadcast method but it seems like a hack and not a real solution.

PS. The reason why I'm adding functions from child controllers into the search factory is because child controllers have access to their local $scope.

Ruzaik
  • 93
  • 7
  • I don't know if using `$broadcast` is a hack, but adding functions to your service from controllers certainly feels like one. You might want to consider refactoring this whole thing with a more sustainable approach. – Lex Jul 27 '16 at 02:29
  • I'm new to Angular. Any direction would be appreciated. – Ruzaik Jul 27 '16 at 02:32
  • Anything that moves you away from adding functions to your service from your controllers seems preferable to your current approach. That's about the best advice I can give you. – Lex Jul 27 '16 at 02:39
  • What if I used [this](http://stackoverflow.com/questions/12576798/angularjs-how-to-watch-service-variables) method? But even this implicitly adds functions into the factory/service. – Ruzaik Jul 27 '16 at 03:43

0 Answers0