Search code examples
angularjsangularjs-httpangularjs-components

angular component one-time binding from $http shows undefined


I'm new to Angular. I'm trying to use components (1.6). In the parent, I have an $http.get that gets data from a service and then assigns the response to a $scope variable. That scope variable is passed to a child component using one-way binding <. In the JavaScript, if I alert the variable passed in, I get "undefined", however, the html template in the child does show the variable. It's like there is a race condition happening and I don't know how to tell it to wait until the data from the service is loaded.

In my parent.js:

(function (angular) {
    'use strict';
    $http.get("http://localhost:52422/api/PayOffYourCc")
    .then(function mySucces(response) {
        $scope.baseline = response.data;

    }
    ,
    function myError(respone) {
        $scope.baseline = response.statusText;

    }
    );
})(window.angular);

In my parent HTML template:

<thermometer baseline="baseline"></thermometer>

In my child component:

(function (angular) {
    'use strict';

    function drawChart(baselineVal) {
        alert(baselineVal);
    }

    function ThermometerController($scope) {
        var ctrl = this;
        ctrl.$onInit = function () {
            drawChart(ctrl.baseline);
        };


    }

    angular.module('payOffYourCcApp').component('thermometer', {
        templateUrl: '../PayOffYourCC/partials/thermometer.html',
        transclude: true,
        controller: ThermometerController,
        bindings: {
            baseline: '<'
        }
    });
})(window.angular);

In my child html template:

<div>
    baseline:{{$ctrl.baseline}}
</div>

In the html, {{$ctrl.baseline}} is displayed fine, but when I alert it in the .js, it's undefined. Why is that? How can I make sure the {{$ctrl.baseline}} is in scope before the javascript loads?


Solution

  • Use the $onChanges life-cycle hook:

    function ThermometerController($scope) {
        var ctrl = this;
        /* REPLACE THIS
        ctrl.$onInit = function () {
            drawChart(ctrl.baseline);
        }; */
        // WITH THIS
        ctrl.$onChanges = function (changesObj) {
            if (changesObj.baseline && changesObj.baseline.currentValue) {
                drawChart(changesObj.baseline.currentValue);
            };
        };
    }
    

    The controller needs to wait for the data to come from the server. By using the $onChanges life-cycle hook, the drawChart function will be called when the data becomes available and will be called on subsequent updates.

    For more information, see AngularJS Comprehensive Directive API Reference - Life-Cycle Hooks.