mirror of
https://github.com/zhigang1992/angular.js.git
synced 2026-04-11 10:59:24 +08:00
fix(ngModel): do not reset bound date objects
Previously, if you bound a `Date` object to `<input type="time">`, whenever you changed the time, the day, month, and year fields of the new resulting bound `Date` object would be reset. Now fields not modified by bound time input elements are copied to the new resulting object. Same for input types of `month`, `week`, etc. Closes #6666
This commit is contained in:
@@ -1004,7 +1004,7 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
|
||||
};
|
||||
}
|
||||
|
||||
function weekParser(isoWeek) {
|
||||
function weekParser(isoWeek, existingDate) {
|
||||
if (isDate(isoWeek)) {
|
||||
return isoWeek;
|
||||
}
|
||||
@@ -1015,9 +1015,21 @@ function weekParser(isoWeek) {
|
||||
if (parts) {
|
||||
var year = +parts[1],
|
||||
week = +parts[2],
|
||||
hours = 0,
|
||||
minutes = 0,
|
||||
seconds = 0,
|
||||
milliseconds = 0,
|
||||
firstThurs = getFirstThursdayOfYear(year),
|
||||
addDays = (week - 1) * 7;
|
||||
return new Date(year, 0, firstThurs.getDate() + addDays);
|
||||
|
||||
if (existingDate) {
|
||||
hours = existingDate.getHours();
|
||||
minutes = existingDate.getMinutes();
|
||||
seconds = existingDate.getSeconds();
|
||||
milliseconds = existingDate.getMilliseconds();
|
||||
}
|
||||
|
||||
return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1025,7 +1037,7 @@ function weekParser(isoWeek) {
|
||||
}
|
||||
|
||||
function createDateParser(regexp, mapping) {
|
||||
return function(iso) {
|
||||
return function(iso, date) {
|
||||
var parts, map;
|
||||
|
||||
if (isDate(iso)) {
|
||||
@@ -1047,14 +1059,26 @@ function createDateParser(regexp, mapping) {
|
||||
|
||||
if (parts) {
|
||||
parts.shift();
|
||||
map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0 };
|
||||
if (date) {
|
||||
map = {
|
||||
yyyy: date.getFullYear(),
|
||||
MM: date.getMonth() + 1,
|
||||
dd: date.getDate(),
|
||||
HH: date.getHours(),
|
||||
mm: date.getMinutes(),
|
||||
ss: date.getSeconds(),
|
||||
sss: date.getMilliseconds()
|
||||
};
|
||||
} else {
|
||||
map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 };
|
||||
}
|
||||
|
||||
forEach(parts, function(part, index) {
|
||||
if (index < mapping.length) {
|
||||
map[mapping[index]] = +part;
|
||||
}
|
||||
});
|
||||
return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0);
|
||||
return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss || 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1072,7 +1096,12 @@ function createDateInputType(type, regexp, parseDate, format) {
|
||||
ctrl.$parsers.push(function(value) {
|
||||
if (ctrl.$isEmpty(value)) return null;
|
||||
if (regexp.test(value)) {
|
||||
var parsedDate = parseDate(value);
|
||||
var previousDate = ctrl.$modelValue;
|
||||
if (previousDate && timezone === 'UTC') {
|
||||
var timezoneOffset = 60000 * previousDate.getTimezoneOffset();
|
||||
previousDate = new Date(previousDate.getTime() + timezoneOffset);
|
||||
}
|
||||
var parsedDate = parseDate(value, previousDate);
|
||||
if (timezone === 'UTC') {
|
||||
parsedDate.setMinutes(parsedDate.getMinutes() - parsedDate.getTimezoneOffset());
|
||||
}
|
||||
|
||||
@@ -2314,6 +2314,17 @@ describe('input', function() {
|
||||
expect(scope.form.alias.$error.month).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should only change the month of a bound date', function() {
|
||||
compileInput('<input type="month" ng-model="value" ng-model-options="{timezone: \'UTC\'}" />');
|
||||
|
||||
scope.$apply(function() {
|
||||
scope.value = new Date(Date.UTC(2013, 7, 1, 1, 0, 0, 0));
|
||||
});
|
||||
changeInputValueTo('2013-12');
|
||||
expect(+scope.value).toBe(Date.UTC(2013, 11, 1, 1, 0, 0, 0));
|
||||
expect(inputElm.val()).toBe('2013-12');
|
||||
});
|
||||
|
||||
describe('min', function (){
|
||||
var scope;
|
||||
beforeEach(inject(function ($rootScope){
|
||||
@@ -2406,6 +2417,18 @@ describe('input', function() {
|
||||
expect(inputElm.val()).toBe('2013-W02');
|
||||
});
|
||||
|
||||
it('should not affect the hours or minutes of a bound date', function (){
|
||||
compileInput('<input type="week" ng-model="secondWeek"/>');
|
||||
|
||||
scope.$apply(function(){
|
||||
scope.secondWeek = new Date(2013, 0, 11, 1, 0, 0, 0);
|
||||
});
|
||||
|
||||
changeInputValueTo('2013-W03');
|
||||
|
||||
expect(+scope.secondWeek).toBe(+new Date(2013, 0, 17, 1, 0, 0, 0));
|
||||
});
|
||||
|
||||
it('should set the model undefined if the input is an invalid week string', function () {
|
||||
compileInput('<input type="week" ng-model="value"/>');
|
||||
|
||||
@@ -2934,6 +2957,17 @@ describe('input', function() {
|
||||
expect(scope.form.alias.$error.time).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should only change hours and minute of a bound date', function() {
|
||||
compileInput('<input type="time" ng-model="value"" />');
|
||||
|
||||
scope.$apply(function(){
|
||||
scope.value = new Date(2013, 2, 3, 1, 0, 0);
|
||||
});
|
||||
|
||||
changeInputValueTo('01:02');
|
||||
expect(+scope.value).toBe(+new Date(2013, 2, 3, 1, 2, 0));
|
||||
});
|
||||
|
||||
describe('min', function (){
|
||||
var scope;
|
||||
beforeEach(inject(function ($rootScope){
|
||||
@@ -3141,6 +3175,50 @@ describe('input', function() {
|
||||
expect(scope.form.alias.$error.date).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should work with multiple date types bound to the same model', function() {
|
||||
formElm = jqLite('<form name="form"></form>');
|
||||
|
||||
var timeElm = jqLite('<input type="time" ng-model="val" />'),
|
||||
monthElm = jqLite('<input type="month" ng-model="val" />'),
|
||||
weekElm = jqLite('<input type="week" ng-model="val" />');
|
||||
|
||||
formElm.append(timeElm);
|
||||
formElm.append(monthElm);
|
||||
formElm.append(weekElm);
|
||||
|
||||
$compile(formElm)(scope);
|
||||
|
||||
scope.$apply(function() {
|
||||
scope.val = new Date(2013, 1, 2, 3, 4, 5, 6);
|
||||
});
|
||||
|
||||
expect(timeElm.val()).toBe('03:04:05');
|
||||
expect(monthElm.val()).toBe('2013-02');
|
||||
expect(weekElm.val()).toBe('2013-W05');
|
||||
|
||||
changeGivenInputTo(monthElm, '2012-02');
|
||||
expect(monthElm.val()).toBe('2012-02');
|
||||
expect(timeElm.val()).toBe('03:04:05');
|
||||
expect(weekElm.val()).toBe('2012-W05');
|
||||
|
||||
changeGivenInputTo(timeElm, '04:05:06');
|
||||
expect(monthElm.val()).toBe('2012-02');
|
||||
expect(timeElm.val()).toBe('04:05:06');
|
||||
expect(weekElm.val()).toBe('2012-W05');
|
||||
|
||||
changeGivenInputTo(weekElm, '2014-W01');
|
||||
expect(monthElm.val()).toBe('2014-01');
|
||||
expect(timeElm.val()).toBe('04:05:06');
|
||||
expect(weekElm.val()).toBe('2014-W01');
|
||||
|
||||
expect(+scope.val).toBe(+new Date(2014, 0, 2, 4, 5, 6, 6));
|
||||
|
||||
function changeGivenInputTo(inputElm, value) {
|
||||
inputElm.val(value);
|
||||
browserTrigger(inputElm, $sniffer.hasEvent('input') ? 'input' : 'change');
|
||||
}
|
||||
});
|
||||
|
||||
describe('min', function (){
|
||||
beforeEach(function (){
|
||||
compileInput('<input type="date" ng-model="value" name="alias" min="2000-01-01" />');
|
||||
|
||||
Reference in New Issue
Block a user