編集 1:バグを修正しましたが、まだ機能していません。
element.val(ngModel.$viewValue || '');
になるはずだった:
dateInput.val(ngModel.$viewValue || '');
EDIT 2 :問題は、分離スコープが原因のようです。スコープがアイソレートの場合、注入されたngModel
の$render()
メソッドが呼び出されません。スコープを非分離にして設定するとng-model="selectedDate"
、$render()
期待どおりに呼び出されます。
EDIT 3:実際には問題は$parent.selectedDate
. に変更するとselectedDate
、コードは正常に機能しているようです。ただし、ディレクティブのスコープで定義されていないことを確認したいのですselectedDate
が、親のスコープから継承されています。というわけで使いたいのですが$parent.
、期待通りに動きません。
ブラウザーが HTML5 日付入力をサポートしている場合はそれを使用し、それ以外の場合は jQuery UI の日付ピッカーを使用するカスタム日付ピッカーを作成しています。これはまだ進行中の作業であり、現在はネイティブの HTML 5 日付入力を使用する部分のみが実装されています。
ディレクティブは次のように使用できます。
<div mil-datepicker ng-model="$parent.selectedDate"></div>
ただし、$scope.selectedDate
初期値がある場合、ディレクティブによってレンダリングされません。また、selectedDate` への外部変更 (たとえば、ボタンをクリックすることによる) は、ディレクティブによって監視されていません。
私のコードで何が間違っている可能性がありますか?
コードのライブ バージョンは次のとおりです: milDatePicker。
ディレクティブのコードは次のとおりです。
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.selectedDate = '2020-01-01';
$scope.changeDate = function() {
$scope.selectedDate = '2030-03-03';
};
});
app.directive('milDatepicker', function () {
var template =
'<div class="mil-datepicker clearfix">' +
' <input type="date" class="form-control">' +
' <div class="btn-group">' +
' <button type="button" class="btn btn-default btn-back">' +
' <span class="glyphicon glyphicon-chevron-left"></span>' +
' </button>' +
' <button type="button" class="btn btn-default btn-reset">Today</button>' +
' <button type="button" class="btn btn-default btn-forward">' +
' <span class="glyphicon glyphicon-chevron-right"></span>' +
' </button>' +
' </div>' +
'</div>';
return {
template: template,
restrict: 'A',
require: 'ngModel',
scope: {},
priority: 0,
link: function (scope, element, attrs, ngModel) {
var nativeDatePickerHandlers = {
back: function () {
var $input = element.find("input").first();
if ($input.val() === '' || $input.val() === undefined) {
return;
}
scope.$apply(function () {
var currentDate = moment($input.val(), "YYYY-MM-DD"),
yesterday = currentDate.subtract('days', 1).format("YYYY-MM-DD");
$input.val(yesterday);
ngModel.$setViewValue(yesterday);
});
},
forward: function () {
var $input = element.find("input").first();
if ($input.val() === '' || $input.val() === undefined) {
return;
}
scope.$apply(function () {
var currentDate = moment($input.val(), "YYYY-MM-DD"),
tomorrow = currentDate.add('days', 1).format("YYYY-MM-DD");
$input.val(tomorrow);
ngModel.$setViewValue(tomorrow);
});
},
reset: function () {
var $input = element.find("input").first();
scope.$apply(function() {
var today = moment().format("YYYY-MM-DD");
$input.val(today);
ngModel.$setViewValue(today);
});
},
change: function () {
var $this = $(this);
scope.$apply(function () {
ngModel.$setViewValue($this.val());
});
}
};
function initNativeDatePicker(element) {
var dateInput = element.find("input").first();
element.find('.btn-back').first().on("click", nativeDatePickerHandlers.back);
element.find('.btn-reset').first().on("click", nativeDatePickerHandlers.reset);
element.find('.btn-forward').first().on("click", nativeDatePickerHandlers.forward);
dateInput.on("change", nativeDatePickerHandlers.change);
ngModel.$render = function () {
dateInput.val(ngModel.$viewValue || '');
};
}
// on browsers that support the HTML 5 date picker just use that
// and do not use the jQuery UI DatePicker
if (Modernizr.inputtypes.date) {
initNativeDatePicker(element);
} else {
}
}
};
});