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