2

Problem: A controller variable vm.boatList (intended to be bound to a service variable, SearchService.boatList) is not updating with the service variable.

Code Snippets: Complete code at the bottom.

Controller

function SearchController($stateParams, SearchService) {
        var vm = this;

        vm.boatList = SearchService.boatList;

Service

function SearchService(BoatsDataService) {

        var service = {
            boatList: null,
            getBoatList: getBoatList,
            params: {}
        };

        return service;

Additional Data:

The getBoatList function called from the controller works - it logs data from the SearchService to the console. When I log vm.boatList immediately afterward, it's null.

Also, <div ng-repeat="boat in SearchController.boatList">...</div> only works when I assign directly to vm.boatList.

Console Output:

Array[3]
null

Complete Controller:

(function () {
    'use strict';

    angular.
        module('trips').
        controller('SearchController', SearchController);

    SearchController.$inject = ['$stateParams', 'SearchService'];

    function SearchController($stateParams, SearchService) {
        var vm = this;

        vm.boatList = SearchService.boatList;
        vm.initialParams = getParams();

        activate();

        ////////////////////

        function activate() {
            setInitialParams();
            SearchService.getBoatList()
                .then(function (data) {
                    SearchService.boatList = data;
                    console.log(SearchService.boatList);  // Logs data.
                    console.log(vm.boatList);  // Logs null.
                })
                .catch(function (error) {
                    console.log(error);
                });
        }

        function getParams() {
            var params = {
                location: $stateParams.location,
                passengers: $stateParams.passengers,
                maxPrice: $stateParams.maxPrice,
                minPrice: $stateParams.minPrice,
                embark: $stateParams.embark,
                disembark: $stateParams.disembark,
                category: $stateParams.category
            };
            return params;
        }

        function setInitialParams() {
            SearchService.params = getParams();
        }
    }
})();

Complete Service:

(function () {
    'use strict';

    angular.
        module('trips').
        factory('SearchService', SearchService);

    SearchService.$inject = ['BoatsDataService'];

    function SearchService(BoatsDataService) {

        var service = {
            boatList: null,
            getBoatList: getBoatList,
            params: {}
        };

        //$scope.$watch('service.params', function () {
        //        getBoatList().then(function (data {
        //            service.boatList = data;
        //        })
        //    }, true
        //);

        return service;

        //////////////////////

        function getBoatList() {
            return BoatsDataService.BoatList
                .query(service.params)
                .$promise
        }
    }
})();

Recap: I don't know how to two-way bind, I guess.

1 Answer 1

1

When you're trying to bind a variable that's directly on the service, it will fail (see call by sharing). However, if you wrap it with an object, it will work like you expect, see this Fiddle.

So in your case, if you bind an object inside the service to your controller, it should be fine -

Service:

var service = {
      boatListObj : {
            boatList: null
      },
      getBoatList: getBoatList,
      params: {}
};

Controller:

vm.boatListObj = SearchService.boatListObj;

Promise response:

.then(function (data) {
        SearchService.boatListObj.boatList = data;
        console.log(SearchService.boatListObj.boatList);  // Logs data.
        console.log(vm.boatListObj.boatList);  // Should log fine now
})

The reason why <div ng-repeat="boat in SearchController.boatList">...</div> is not working is because SearchController.boatList is not on the $scope. It either must be on the $scope, or addressed via ControllerAs syntax when it's placed on the controller.

Sign up to request clarification or add additional context in comments.

2 Comments

This works, thanks! My follow-up is: why doesn't boatList = {} work, since that creates an empty object? In fact, when I use that syntax it logs to the console as an Object. My understanding based on some reading is that as long as the bound variable isn't a primitive, it would set up the automatic $watch.
It's not working because you're trying to override it when you're doing boatList = ... afterwards, meaning you're trying to change boatList's reference. Notice that in the solution you're modifying a variable inside an object, and not changing the wrapper object to point to a different object.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.