我正在创建简单的ui-datetime指令.它将javascript Date对象拆分为_date,_hours和_minutes部分._date使用jquery ui datepicker,_hours和_minutes - 数字输入.
angular.module("ExperimentsModule", [])
.directive("uiDatetime", function () {
return {
restrict: 'EA',
replace: true,
template: '<div class="ui-datetime">' +
'<input type="text" ng-model="_date" class="date">' +
'<input type="number" ng-model="_hours" min="0" max="23" class="hours">' +
'<input type="number" ng-model="_minutes" min="0" max="59" class="minutes">' +
'<br />Child datetime1: {{datetime1}}' +
'</div>',
require: 'ngModel',
scope: true,
link: function (scope, element, attrs, ngModelCtrl) {
var elDate = element.find('input.date');
ngModelCtrl.$render = function () {
var date = new Date(ngModelCtrl.$viewValue);
var fillNull = function (num) {
if (num < 10) return '0' + num;
return num;
};
scope._date = fillNull(date.getDate()) + '.' + fillNull(date.getMonth() + 1) + '.' + date.getFullYear();
scope._hours = date.getHours();
scope._minutes = date.getMinutes();
};
elDate.datepicker({
dateFormat: 'dd.mm.yy',
onSelect: function (value, picker) {
scope._date = value;
scope.$apply();
}
});
var watchExpr = function () {
var res = scope.$eval('_date').split('.');
if (res.length == 3) return new Date(res[2], res[1] - 1, res[0], scope.$eval('_hours'), scope.$eval('_minutes'));
return 0;
};
scope.$watch(watchExpr, function (newValue) {
ngModelCtrl.$setViewValue(newValue);
}, true);
}
};
});
function TestController($scope) {
$scope.datetime1 = new Date();
}
Run Code Online (Sandbox Code Playgroud)
在github上:https://github.com/andreev-artem/angular_experiments/tree/master/ui-datetime
据我所知 - 创建新组件时的最佳做法是使用隔离范围.
当我尝试使用隔离范围时 - 没有任何作用.ngModel.$ viewValue === undefined.
当我尝试使用新范围时(我的例子,不是那么好的变体imho) - ngModel在新创建的范围上使用值.
当然,我可以使用隔离范围创建指令,并通过"= expression"(示例)使用ngModel值.但我认为使用ngModelController是一种更好的做法.
我的问题:
Mar*_*cok 18
scope: true
用scope: { datetime1: '=ngModel'}
你的第一个小提琴替换似乎工作得很好 - 小提琴.不幸的是,你的"示例"小提琴的链接被打破了,所以我不确定你在那里尝试了什么.
因此,似乎ngModelController可以与隔离范围一起使用.
这是一个较小的小提琴,它使用HTML /视图中的ng-model,一个隔离范围,以及链接函数中的$ setViewValue: 小提琴.
更新:我刚刚发现了一些相当有趣的东西:如果隔离范围属性被赋予了不同的名称 - 例如,说dt1而不是datetime1 scope: { dt1: '=ngModel'}
- 它就不再有用了!我猜测,当我们require: 'ngModel'
,ngModelController使用HTML /视图中的名称(即ng-model属性值)在隔离范围上创建属性.因此,如果我们在对象哈希中指定相同的名称,那么一切都很好.但是如果我们指定一个不同的名称,那么新的scope属性(例如,dt1)就不会与我们需要的ngModelController相关联.
这是一个更新的小提琴.
使您的指令以比 ngModel 更高的优先级运行,并更正隔离范围的模型绑定。我选择了优先级“100”,它与输入指令的级别相同,在像 ngRepeat 这样的高优先级模板操作之后,但在默认值 0 之前,这是 ngModel 使用的。
这是示例代码:
myDirective = function() {
return {
compile: function(tElement, tAttrs, transclude) {
// Correct ngModel for isolate scope
if (tAttrs.ngModel) {
tAttrs.$set('model', tAttrs.ngModel, false);
tAttrs.$set('ngModel', 'model', false);
}
return {
post: function(scope, iElement, iAttrs, controller) {
// Optionally hook up formatters and parsers
controller.$formatters.push(function(value) {
// ...
})
// Render
return controller.$render = function() {
if (!controller.$viewValue) {
return;
}
angular.extend(scope, controller.$viewValue);
};
}
};
},
priority: 100,
require: '^ngModel',
scope: {
model: '='
},
};
}
Run Code Online (Sandbox Code Playgroud)
在编译期间,该指令检查 ngModel 属性是否存在。此检查使用 Angular 的Attributes对标准化值进行检查。如果该属性存在,它将被替换为“model”(而不是“ngModel”),这是数据绑定到隔离中的名称。然而,我们还必须创建一个属性,以便 Angular 可以为我们执行数据绑定。这两个属性都可以(根据您的选择)使用false
参数进行修改,从而使 DOM 保持不变。
归档时间: |
|
查看次数: |
26292 次 |
最近记录: |