试图从隔离范围观察变量

时间:2015-11-30 03:11:31

标签: angularjs angularjs-directive

创建自定义指令的新功能。它在初始渲染时渲染得很好。但是,我正在尝试$watch更改原始数据,然后触发更新。

作为一个快速测试,我创建了一个按钮并使用jQuery来更新costPerDay.costs数组(手动)...但是$ watch仍然不会触发&我的断点没有到达。

感谢您的帮助...

我的控制器看起来像:
GET被模拟为返回一个对象,而不是一个promise,所以忽略那个特定的行。一旦我使$ watch工作,我将相应地更新这部分代码。

// CONTROLLER
application.controller('HomeIndexController', function ($scope, costPerDayDataService) {
    var vm = this;

    // Internal
    vm.on = {
        databind: {
            costPerDay: function () {
                // The GET is mocked to return an object, not a promise, so ignore this line
                var costPerDay = costPerDayDataService.get();
                $scope.data.costPerDay = costPerDay;
            }
        }
    };
    vm.databind = function () {
        vm.on.databind.costPerDay();
    };

    // Scope
    $scope.data = {
        costPerDay: {}
    };

    $scope.on = {
        alterCosts: function (e) {
            var costs = [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300];
            $scope.data.costPerDay.costs = costs;
        }
    }

    // Databind
    vm.databind();
});

我的元素看起来像:
这最初很好。我需要自动更新。

<ul id="sparks" class="pull-down pull-left">
    <li cost-per-day-sparkline costperday="data.costPerDay">
    </li>
</ul>

我的指示看起来像:
我只是想让其中一个人工作......当我得到一个有效的例子时,我显然会删除其他人。是的,我知道你不应该直接更新$parent。我只是想在找到想象之前找到一个有效的组合。

define([], function () {
    'use strict';

    function CostPerDaySparklineDirective() {
        return {
            replace: true,
            restrict: "AE",
            scope: {
                costperday: "=costperday"
            },
            templateUrl: '/modules/templates/sparklines/costperdaysparklinetemplate.html',
            link: function (scope, elem, attrs) {


                // This fails       
                scope.$watch('costperday', function (newval) {
                    // ... code to update will go here
                }, true);

                // This fails           
                scope.$watch('costperday', function (newval) {
                    // ... code to update will go here
                });

                // This fails
                scope.$parent.$watch('data.costPerDay.costs', function (newval) {
                    // ... code to update will go here
                });

                // This renders initially, but fails to fire again
                scope.$watch('scope.$parent.data.costPerDay.costs', function (newval) {
                    var eleSparkline = $('.sparkline', elem);
                    eleSparkline.sparkline(scope.costperday.costs, { type: "bar" });
                });
            }
        };
    }

    return CostPerDaySparklineDirective;
});

更新
即使使用ng-click来测试$ watch也无法达到断点......

<a ng-click="on.alterCosts()">Change Costs</a>

2 个答案:

答案 0 :(得分:1)

在这种情况下,我会观察costPerDayDataService与侦听控制器范围变量的实际获取。所以在你的控制器中,你可以在costPerDayDataService中设置变量,在你的指令中你只需注入你的服务并观察get函数。或者,如果您使用的是1.3.x&gt;你可以使用bindToController我相信消除了对手表的全部需求。

bindToController: {
  costperday: '='
}

答案 1 :(得分:1)

在这种情况下,我会在$scope.$apply();方法中运行alterCosts来触发模板摘要。这将更新您的指令捕获的DOM中的值,然后触发$ watch。

有关$apply()的更多信息,https://docs.angularjs.org/api/ng/type/ $ rootScope.Scope#$ apply

&#34; $ apply()用于从角度框架外部以角度执行表达式。 (例如,来自浏览器DOM事件..&#34;

在此特定情况下,您需要更改DOM事件的值。