@@ -1061,18 +1061,23 @@ var inputType = {
1061
1061
* Angular will also update the model value.
1062
1062
*
1063
1063
* Automatic value adjustment also means that a range input element can never have the `required`,
1064
- * `min`, or `max` errors.
1065
- *
1066
- * Note that `input[range]` is not compatible with`ngMax` and `ngMin`, because they do not set the
1067
- * `min` and `max` attributes, which means that the browser won't automatically adjust the input
1068
- * value based on their values, and will always assume min = 0 and max = 100.
1064
+ * `min`, or `max` errors, except when using `ngMax` and `ngMin`, which are not affected by automatic
1065
+ * value adjustment, because they do not set the `min` and `max` attributes.
1069
1066
*
1070
1067
* @param {string } ngModel Assignable angular expression to data-bind to.
1071
1068
* @param {string= } name Property name of the form under which the control is published.
1072
1069
* @param {string= } min Sets the `min` validation to ensure that the value entered is greater
1073
1070
* than `min`. Can be interpolated.
1074
1071
* @param {string= } max Sets the `max` validation to ensure that the value entered is less than `max`.
1075
1072
* Can be interpolated.
1073
+ * @param {string= } ngMin Takes an expression. Sets the `min` validation to ensure that the value
1074
+ * entered is greater than `min`. Does not set the `min` attribute and therefore
1075
+ * adds no native HTML5 validation. It also means the browser won't adjust the
1076
+ * element value in case `min` is greater than the current value.
1077
+ * @param {string= } ngMax Takes an expression. Sets the `max` validation to ensure that the value
1078
+ * entered is less than `max`. Does not set the `max` attribute and therefore
1079
+ * adds no native HTML5 validation. It also means the browser won't adjust the
1080
+ * element value in case `max` is less than the current value.
1076
1081
* @param {string= } ngChange Angular expression to be executed when the ngModel value changes due
1077
1082
* to user interaction with the input element.
1078
1083
*
@@ -1542,12 +1547,10 @@ function rangeInputType(scope, element, attr, ctrl, $sniffer, $browser) {
1542
1547
numberFormatterParser ( ctrl ) ;
1543
1548
baseInputType ( scope , element , attr , ctrl , $sniffer , $browser ) ;
1544
1549
1545
- var supportsRange = ctrl . $$hasNativeValidators && element [ 0 ] . type === 'range' ,
1546
- minVal = supportsRange ? 0 : undefined ,
1547
- maxVal = supportsRange ? 100 : undefined ,
1548
- validity = element [ 0 ] . validity ,
1549
- hasMinAttr = isDefined ( attr . min ) ,
1550
- hasMaxAttr = isDefined ( attr . max ) ;
1550
+ var minVal = 0 ,
1551
+ maxVal = 100 ,
1552
+ supportsRange = ctrl . $$hasNativeValidators && element [ 0 ] . type === 'range' ,
1553
+ validity = element [ 0 ] . validity ;
1551
1554
1552
1555
var originalRender = ctrl . $render ;
1553
1556
@@ -1560,39 +1563,6 @@ function rangeInputType(scope, element, attr, ctrl, $sniffer, $browser) {
1560
1563
} :
1561
1564
originalRender ;
1562
1565
1563
- if ( hasMinAttr ) {
1564
- ctrl . $validators . min = supportsRange ?
1565
- // Since all browsers set the input to a valid value, we don't need to check validity
1566
- function noopMinValidator ( ) { return true ; } :
1567
- // non-support browsers validate the range
1568
- function minValidator ( modelValue , viewValue ) {
1569
- return ctrl . $isEmpty ( viewValue ) || isUndefined ( minVal ) || viewValue >= minVal ;
1570
- } ;
1571
-
1572
- setInitialValueAndObserver ( 'min' , minChange ) ;
1573
- }
1574
-
1575
- if ( hasMaxAttr ) {
1576
- ctrl . $validators . max = supportsRange ?
1577
- // Since all browsers set the input to a valid value, we don't need to check validity
1578
- function noopMaxValidator ( ) { return true ; } :
1579
- // ngMax doesn't set the max attr, so the browser doesn't adjust the input value as setting max would
1580
- function maxValidator ( modelValue , viewValue ) {
1581
- return ctrl . $isEmpty ( viewValue ) || isUndefined ( maxVal ) || viewValue <= maxVal ;
1582
- } ;
1583
-
1584
- setInitialValueAndObserver ( 'max' , maxChange ) ;
1585
- }
1586
-
1587
- function setInitialValueAndObserver ( htmlAttrName , changeFn ) {
1588
- // interpolated attributes set the attribute value only after a digest, but we need the
1589
- // attribute value when the input is first rendered, so that the browser can adjust the
1590
- // input value based on the min/max value
1591
- element . attr ( htmlAttrName , attr [ htmlAttrName ] ) ;
1592
-
1593
- attr . $observe ( htmlAttrName , changeFn ) ;
1594
- }
1595
-
1596
1566
function minChange ( val ) {
1597
1567
if ( isDefined ( val ) && ! isNumber ( val ) ) {
1598
1568
val = parseFloat ( val ) ;
@@ -1603,12 +1573,12 @@ function rangeInputType(scope, element, attr, ctrl, $sniffer, $browser) {
1603
1573
return ;
1604
1574
}
1605
1575
1606
- if ( supportsRange ) {
1576
+ if ( supportsRange && minAttrType === 'min' ) {
1607
1577
var elVal = element . val ( ) ;
1608
1578
// IE11 doesn't set the el val correctly if the minVal is greater than the element value
1609
1579
if ( minVal > elVal ) {
1580
+ element . val ( minVal ) ;
1610
1581
elVal = minVal ;
1611
- element . val ( elVal ) ;
1612
1582
}
1613
1583
ctrl . $setViewValue ( elVal ) ;
1614
1584
} else {
@@ -1617,6 +1587,23 @@ function rangeInputType(scope, element, attr, ctrl, $sniffer, $browser) {
1617
1587
}
1618
1588
}
1619
1589
1590
+ var minAttrType = isDefined ( attr . ngMin ) ? 'ngMin' : isDefined ( attr . min ) ? 'min' : false ;
1591
+ if ( minAttrType ) {
1592
+ ctrl . $validators . min = isDefined ( attr . min ) && supportsRange ?
1593
+ function noopMinValidator ( value ) {
1594
+ // Since all browsers set the input to a valid value, we don't need to check validity
1595
+ return true ;
1596
+ } :
1597
+ // ngMin doesn't set the min attr, so the browser doesn't adjust the input value as setting min would
1598
+ function minValidator ( modelValue , viewValue ) {
1599
+ return ctrl . $isEmpty ( viewValue ) || isUndefined ( minVal ) || viewValue >= minVal ;
1600
+ } ;
1601
+
1602
+ // Assign minVal when the directive is linked. This won't run the validators as the model isn't ready yet
1603
+ minChange ( attr . min ) ;
1604
+ attr . $observe ( 'min' , minChange ) ;
1605
+ }
1606
+
1620
1607
function maxChange ( val ) {
1621
1608
if ( isDefined ( val ) && ! isNumber ( val ) ) {
1622
1609
val = parseFloat ( val ) ;
@@ -1627,20 +1614,35 @@ function rangeInputType(scope, element, attr, ctrl, $sniffer, $browser) {
1627
1614
return ;
1628
1615
}
1629
1616
1630
- if ( supportsRange ) {
1617
+ if ( supportsRange && maxAttrType === 'max' ) {
1631
1618
var elVal = element . val ( ) ;
1632
1619
// IE11 doesn't set the el val correctly if the maxVal is less than the element value
1633
1620
if ( maxVal < elVal ) {
1634
1621
element . val ( maxVal ) ;
1635
- // IE11 and Chrome don't set the value to the minVal when max < min
1636
- elVal = maxVal < minVal ? minVal : maxVal ;
1622
+ elVal = minVal ;
1637
1623
}
1638
1624
ctrl . $setViewValue ( elVal ) ;
1639
1625
} else {
1640
1626
// TODO(matsko): implement validateLater to reduce number of validations
1641
1627
ctrl . $validate ( ) ;
1642
1628
}
1643
1629
}
1630
+ var maxAttrType = isDefined ( attr . max ) ? 'max' : attr . ngMax ? 'ngMax' : false ;
1631
+ if ( maxAttrType ) {
1632
+ ctrl . $validators . max = isDefined ( attr . max ) && supportsRange ?
1633
+ function noopMaxValidator ( ) {
1634
+ // Since all browsers set the input to a valid value, we don't need to check validity
1635
+ return true ;
1636
+ } :
1637
+ // ngMax doesn't set the max attr, so the browser doesn't adjust the input value as setting max would
1638
+ function maxValidator ( modelValue , viewValue ) {
1639
+ return ctrl . $isEmpty ( viewValue ) || isUndefined ( maxVal ) || viewValue <= maxVal ;
1640
+ } ;
1641
+
1642
+ // Assign maxVal when the directive is linked. This won't run the validators as the model isn't ready yet
1643
+ maxChange ( attr . max ) ;
1644
+ attr . $observe ( 'max' , maxChange ) ;
1645
+ }
1644
1646
1645
1647
}
1646
1648
0 commit comments