1

Sometimes svg chart appear more small than normal. This problem is solved Reloading Screen.

//Values Graphic
$scope.$watch(vm.dataGraphic.watch, function () {
    var data = vm.dataGraphic.watch ? $scope.$eval(vm.dataGraphic.watch) : vm.dataGraphic;

    setTimeout(sleep,500); //patch to "solve" this issue

    function sleep(){
        vm.dataValues = getDataValues(data);
    }

});
function getDataValues(data) {
    vm.dataGraphic = data || dataGraphicTest;
    if (vm.dataGraphic.values.length == 0) {
        return [];
    } else {
        vm.dataKeyValues = transformForKeyValues(vm.dataGraphic.values, vm.dataGraphic.accumulated);

        vm.barValues = transformBarValues(vm.dataGraphic.values, vm.dataGraphic.limit);
        var lineValues = transformLineValues(vm.barValues, vm.dataGraphic.limit, vm.dataGraphic.accumulated, vm.dataGraphic.startMonthlyLimit);
        vm.maxY = calculateMaxY(vm.barValues, lineValues);

        return [
            {
            "key": vm.dataGraphic.labelX.name,
            "bar": true,
            "color": _graphicsColors.bar,
            "values": vm.barValues
            },
            {
            "key": _graphicsValorPorDefecto,
            "color": _graphicsColors.line,
            "values": lineValues
            }
        ];
    }
}

SVG element with the following html tags appears with wrong dimensions.

<g class="nvd3 nv-wrap nv-linePlusBar" transform="translate(35,10)">

This problem does not always happen, but when it happens is arranged refreshing the screen.

I think this patch is a bad idea and I would like to understand what is happening .

Thanks

mjimcua
  • 2,781
  • 3
  • 27
  • 47

1 Answers1

2

I think your problem ultimately stems from your watch:

$scope.$watch(vm.dataGraphic.watch, function () {
    var data = vm.dataGraphic.watch ? $scope.$eval(vm.dataGraphic.watch) : vm.dataGraphic;

    setTimeout(sleep,500); //patch to "solve" this issue

    function sleep(){
        vm.dataValues = getDataValues(data);
    }

});

The problem I see is that you're using setTimeout to call your sleep function a half second after the watch fires. As it is now, this will be fine if your $digest is still running in 500ms. setTimeout is a vanilla JavaScript function, so calling it won't notify angularjs that there are any changes after the $digest has ended. Angular only triggers a $digest after 'user-initiated' events like ajax, clicks, entering data, etc. (read more here). If the $digest is running, you'll get lucky and angularjs will just happen to see those changes. You'll need to inform angular of your changes using $scope.$apply:

$scope.$watch(vm.dataGraphic.watch, function () {
    var data = vm.dataGraphic.watch ? $scope.$eval(vm.dataGraphic.watch) : vm.dataGraphic;

    setTimeout(sleep,500); //patch to "solve" this issue

    function sleep(){
        vm.dataValues = getDataValues(data);
        $scope.$apply();
    }

});

There are a lot of ways to use $scope.$apply, so be sure to check out the documentation. Also do a search on something like 'when to use $scope.$apply' and you'll find a lot of people for and against it. It does trigger another $digest loop, which can be costly if you have a lot of bindings or if you're at the end of the final digest loop and apply causes it to start over.

I don't think it's actually a good idea to be updating your model using setTimeout from within a watch function. Does this not work without it? You may have some other async code that needs to be applied in the same fashion. Generally, you want $scope.$apply to be as close to the non-angular asynchronous code as possible.

Joseph Yaduvanshi
  • 20,241
  • 5
  • 61
  • 69
  • Thanks for your answer. setTimeout is only a patch, no belongs to the main code. With setTimeout works but I think that it isn't a good idea – mjimcua Feb 27 '15 at 12:41