Angularjs 如何在指令链接阶段访问角度范围值?

Angularjs 如何在指令链接阶段访问角度范围值?,angularjs,angularjs-directive,Angularjs,Angularjs Directive,我有一个显示datetimepicker的元素。它是时区敏感的。时间作为item.time存储在范围中的item对象中,而TZ作为item.timezone存储 我创建了一个指令来呈现它。为了实际正确渲染,它需要知道时区,但在链接时间,当它全部处理完毕时,控制器尚未正确加载项。。。或者我会这么想,但它正确地加载了item,因为item.time就在那个里。尽管如此,在调用格式化程序时,它将attrs.timezone作为,即使modelValue已正确加载 HTML: 还有JS,去掉大部分

我有一个显示datetimepicker的元素。它是时区敏感的。时间作为item.time存储在范围中的item对象中,而TZ作为item.timezone存储

我创建了一个指令来呈现它。为了实际正确渲染,它需要知道时区,但在链接时间,当它全部处理完毕时,控制器尚未正确加载项。。。或者我会这么想,但它正确地加载了item,因为item.time就在那个里。尽管如此,在调用格式化程序时,它将attrs.timezone作为,即使modelValue已正确加载

HTML:

还有JS,去掉大部分

    .directive('datetimepicker',function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        template: '<span><input readonly="readonly"></input><span class="glyphicon glyphicon-calendar"></span></span>',
        replace: true,
        link: function ($scope,element,attrs,ngModel) {
            var format = "YYYY-MM-DD H:mm",
            formatter = function (modelValue) {
                // HERE IS MY PROBLEM: at this point, modelValue does == item.time, but attrs.timezone is "", even though I know it loads correctly!
                var ret = modelValue ? moment(modelValue) : "", mtz;
                if (ret.tz) {
                    mtz = ret.tz(attrs.timezone);
                }
                if (mtz) {
                    ret = mtz.format(format);
                } else if (ret.format) {
                    ret = ret.format(format);
                }
                return ret;
            };
    ngModel.$formatters.push(formatter);
    };
})
编辑:

angular正在正确评估元素上的attr时区;它只是在link函数中不可用,甚至在格式化程序中也不可用。以下是加载后的html:

<span timezone="America/Winnipeg" ng-model="item.time" datetimepicker="true" class="ng-valid ng-valid-datetime ng-dirty">
   <input readonly="readonly"/><span class="glyphicon glyphicon-calendar">
</span>
编辑:添加控制器,高度简化

    .controller('ItemDetail',['$scope','Item',
    function ($scope,Item) {
        var itemId = "40"; // not really, but good enough for here
        Item.get({item: itemId},function (item) {
            $scope.item = item;
        },function (httpResponse) {
            // do error reporting
        });
        // click button to enter edit mode, which hides <span> showing time and shows input with datepicker
        $scope.edit = function () {
            $scope.editMode = true;
        };
        $scope.save = function () {
            // save the updates
            $scope.item.$save();
            $scope.editMode = false;
        };
        $scope.cancel = function () {
            // cancel any updates
            $scope.item.$reset();
            $scope.editMode = false;
        };
    }])

我认为应该使用隔离作用域,通过属性bindings=binding绑定作用域变量,并使用scope.$watch通过回调设置时区:

// directive scope binding
scope: {
  timezone: '='
}

// watch local scope var in the link function since it's now binded
scope.$watch('timezone',function(newval, oldval){
  // do what you need to do from here when the timezone var gets set
  mtz = ret.tz(attrs.timezone);
});

这与您在属性绑定中绑定到item.timezone的位置将item.tz作为item.tz引用的时区属性有关吗?@jdmcnair我希望如此,但我只是草率地将其复制到stackoverflow中。在实际代码中,它始终是item.timezone。你能给我你的控制器吗?或使用plunkerSure的完整代码。向上编辑。添加了控制器。没什么特别的,只是装了一件东西。这很接近。我甚至不需要一个孤立的范围;我所能做的就足够了,然后只需要作用域。$watchattrs.timezone,函数{…};虽然隔离范围也可以工作。但是我该如何重新触发格式化程序呢?如果你的格式化程序依赖于这个值,我只需要在$watch中创建并添加格式化程序。如果两个格式化程序都有独立的异步依赖项,则由您决定用户是否应该能够在加载格式化程序时进行编辑,或者是否可能生成并推送两个不同的格式化程序,我喜欢明确地将隔离作用域绑定声明为我的指令依赖性,因为我认为它更干净、更容易混淆。我可以看到,尽管在我将项传递回要保存的位置时可能会混淆。这很公平,但您也可以使用作用域函数绑定。无论哪种方式,都取决于您的具体应用。希望这有帮助
// directive scope binding
scope: {
  timezone: '='
}

// watch local scope var in the link function since it's now binded
scope.$watch('timezone',function(newval, oldval){
  // do what you need to do from here when the timezone var gets set
  mtz = ret.tz(attrs.timezone);
});