概述
Angular js的input指令是對html中的input元素的一個封裝释涛,Angular js中的input指令使得input的功能更加豐富,完善财忽。input元素是一個具有多種類型呈宇,如:button,text等扒俯。Angular js的input指令只對其中一部分類型進行了封裝奶卓,有五種類型是直接使用的html的input元素,任何Angular js無法識別的類型都會默認使用text類型進行處理撼玄。
Input指令對于各種類型的處理情況:
類型 | 是否封裝 |
---|---|
text | 是 |
date | 是 |
datetime-local | 是 |
time | 是 |
week | 是 |
month | 是 |
number | 是 |
url | 是 |
是 | |
radio | 是 |
range | 是 |
checkbox | 是 |
hidden | 否 |
button | 否 |
submit | 否 |
reset | 否 |
file | 否 |
詳細說明
各種類型的公共部分
input指令在對每一種type進行處理的時候都會預先進行基本操作寝杖,這個操作主要是進行事件監(jiān)聽等工作。其中重點有:
1互纯、對于android系統(tǒng)瑟幕,會監(jiān)聽compositionstart和compositionend消息,這兩個消息是在使用輸入法輸入時慘的留潦。接到start消息就會停止對input的處理只盹,接到end消息后就會開始對input的處理。
2兔院、Angular會監(jiān)聽input消息殖卑,如果沒有input消息就會監(jiān)聽keydown、paste坊萝、cut消息孵稽,然后進行相應的處理。
3十偶、對于date,datetime-local,month,time,week這些類型菩鲜,如果直接改變了validity,是無法及時響應的惦积,這是由于validity的變化不一定會發(fā)送input或change消息接校,所以對于這些類型增加了一個監(jiān)聽keydown wheel mousedown的消息,在這些消息處理過程中判斷validity是否有改變狮崩,如果改變了就進行相應的處理蛛勉。
公共處理部分的核心鹿寻,所有的事件監(jiān)聽都是為了這個部分:
var listener = function(ev) {
if (timeout) {
$browser.defer.cancel(timeout);
timeout = null;
}
if (composing) return;
var value = element.val(),
event = ev && ev.type;
// By default we will trim the value
// If the attribute ng-trim exists we will avoid trimming
// If input type is 'password', the value is never trimmed
if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) {
value = trim(value);
}
// If a control is suffering from bad input (due to native validators), browsers discard its
// value, so it may be necessary to revalidate (by calling $setViewValue again) even if the
// control's value is the same empty value twice in a row.
if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) {
ctrl.$setViewValue(value, event);
}
};
這個消息響應的方法主要做的事情:
1、各種輸入判斷诽凌,如果composing狀態(tài)如果為true毡熏,就不處理。
2侣诵、輸入的值的預處理痢法。
3、把input的值設置到view上去窝趣。
各種不同類型的處理過程
文本類型
text
text為基本類型,沒有進行過多的處理训柴,只是直接把輸入的值設置到元素上去哑舒。
url
url會在text的基礎上再增加一個url驗證器的設置,主要是驗證url有效性的時候使用幻馁。
email和url類似洗鸵,相對于text增加了一個email的驗證器。
日期
日期類型主要包括:date仗嗦,datetime-local膘滨,time,week稀拐,month火邓。
所有的日期類型的input指令都有一個共同的部分:日期解析。除了week類型外德撬,其它都是使用同一個函數(shù):createDateParser铲咨,該函數(shù)會返回一個函數(shù),在這個函數(shù)中會進行日期解析蜓洪,日期解析的核心代碼:
regexp.lastIndex = 0;
parts = regexp.exec(iso);
if (parts) {
parts.shift();
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() / 1000
};
} 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, map.sss * 1000 || 0);
}
這段代碼中主要的工作:
1纤勒、時間日期的解析,正則表達式regexp作為參數(shù)傳入隆檀。
/^(\d{4,})-(\d{2})-(\d{2})$/ \\date
/^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/ \\datetime-localb
/^(\d{4,})-(\d\d)$/ \\month
/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/ \\time
2摇天、新建一個時間對象,如果傳入了默認值恐仑,就會復制默認值泉坐,如果沒有傳入,就指定為1970-01-01 00:00:00裳仆。
3坚冀、把解析到的數(shù)據(jù)拷貝的相應的位置上。
日期類型都具有最大值和最小值控制鉴逞,可以使用ng-max记某、max或者ng-min司训、min指定。
數(shù)值類型
數(shù)值類型主要有:number和range液南,他們兩的功能幾乎是一模一樣的壳猜。
數(shù)值類型主要是增加了一些屬性的處理,包括:ng-max滑凉,ng-min统扳,max,min畅姊,step咒钟。
其中需要說明的是step屬性,其處理代碼:
if (isDefined(attr.step) || attr.ngStep) {
var stepVal;
ctrl.$validators.step = function(modelValue, viewValue) {
return ctrl.$isEmpty(viewValue) || isUndefined(stepVal) || viewValue % stepVal === 0;
};
attr.$observe('step', function(val) {
stepVal = parseNumberAttrVal(val);
// TODO(matsko): implement validateLater to reduce number of validations
ctrl.$validate();
});
}
可以看出當定義了step屬性若未,或者ng-step屬性的時候朱嘴,number的值必須是step的整數(shù)倍。同事還會監(jiān)控tep屬性粗合,目前當發(fā)現(xiàn)step變化時只是簡單的再次判斷是否有效萍嬉。
單選框類型
對于單選框radio類型,input指令主要做的工作:
1隙疚、如果沒有定義name屬性壤追,就添加一個name屬性,使用調(diào)用angualr的nextUid方法得到name的值供屉。
2行冰、監(jiān)聽click事件和value變化事件,然后處理伶丐。
復選框類型
對于復選框checkbox類型资柔,input指令主要增加了ng-true-value和ng-false-value屬性。通過這兩個屬性可以指定自定義的true和false撵割,如:Yes和No等贿堰,理論上可以為任何值。如果input的value等于ng-true-value的值就是選中啡彬,否則就是補選中羹与。如果沒有設置這兩個屬性,ng-true-value = true庶灿,ng-false-alue= false纵搁。
代碼樣例
字符串類型
<!DOCTYPE html>
<html lang="en" ng-app="app">
<!--<html>-->
<head>
<title>Test</title>
</head>
<body>
<form name="myForm" ng-controller="ExampleController">
<div>Single word:
<input type="text" name="inputText" ng-model="example.text" required ng-trim="false">
</div>
<div>URL:
<input type="url" name="inputUrl" ng-model="example.url" required>
<label>
<div role="alert">
<span class="error" ng-show="myForm.inputUrl.$error.required">
Required!</span>
<span class="error" ng-show="myForm.inputUrl.$error.url">
Not valid url!</span>
</div>
</label>
</div>
<div>Email:
<input type="email" name="inputEmail" ng-model="example.email" required>
<div role="alert">
<span class="error" ng-show="myForm.inputEmail.$error.required">
Required!</span>
<span class="error" ng-show="myForm.inputEmail.$error.email">
Not valid email!</span>
</div>
</div>
<label>Pick a date in 2013:</label>
<input type="date" name="inputDate" ng-model="example.date"
placeholder="yyyy-MM-dd" min="2013-01-01" max="2013-12-31" required />
<div role="alert">
<span class="error" ng-show="myForm.inputDate.$error.required">
Required!</span>
<span class="error" ng-show="myForm.inputDate.$error.date">
Not a valid date!</span>
</div>
<label>Pick a date between in 2013:</label>
<input type="datetime-local" name="inputLocal" ng-model="example.local"
placeholder="yyyy-MM-ddTHH:mm:ss" min="2001-01-01T00:00:00" max="2013-12-31T00:00:00" required />
<div role="alert">
<span class="error" ng-show="myForm.inputLocal.$error.required">
Required!</span>
<span class="error" ng-show="myForm.inputLocal.$error.datetimelocal">
Not a valid date!</span>
</div>
<label >Pick a time between 8am and 5pm:</label>
<input type="time" name="inputTime" ng-model="example.time"
placeholder="HH:mm:ss" min="08:00:00" max="17:00:00" required />
<div role="alert">
<span class="error" ng-show="myForm.inputTime.$error.required">
Required!</span>
<span class="error" ng-show="myForm.inputTime.$error.time">
Not a valid date!</span>
</div>
<label>Pick a date between in 2013:
<input type="week" name="inputWeek" ng-model="example.week"
placeholder="YYYY-W##" min="2012-W32"
max="2013-W52" required />
</label>
<div role="alert">
<span class="error" ng-show="myForm.inputWeek.$error.required">
Required!</span>
<span class="error" ng-show="myForm.inputWeek.$error.week">
Not a valid date!</span>
</div>
<label >Pick a month in 2013:</label>
<input type="month" name="inputMonth" ng-model="example.month"
placeholder="yyyy-MM" min="2013-01" max="2013-12" required />
<div role="alert">
<span class="error" ng-show="myForm.inputMonth.$error.required">
Required!</span>
<span class="error" ng-show="myForm.inputMonth.$error.month">
Not a valid month!</span>
</div>
<label>Number:
<input type="number" name="inputNumber" ng-model="example.number"
min="0" max="99" required>
</label>
<div role="alert">
<span class="error" ng-show="myForm.inputNumber.$error.required">
Required!</span>
<span class="error" ng-show="myForm.inputNumber.$error.number">
Not valid number!</span>
</div>
Model as range: <input type="range" name="range" ng-model="example.range" min="{{example.min}}" max="{{example.max}}">
<hr>
Model as number: <input type="number" ng-model="example.range"><br>
Min: <input type="number" ng-model="example.min"><br>
Max: <input type="number" ng-model="example.max"><br>
value = <code>{{example.range}}</code><br/>
myForm.range.$valid = <code>{{myForm.range.$valid}}</code><br/>
myForm.range.$error = <code>{{myForm.range.$error}}</code>
<div>
<label>
<input type="radio" ng-model="color.name" value="red">
Red
</label><br/>
<label>
<input type="radio" ng-model="color.name" ng-value="specialValue">
Green
</label><br/>
<label>
<input type="radio" ng-model="color.name" value="blue">
Blue
</label><br/>
</div>
<div>
<label>Value1:
<input type="checkbox" ng-model="checkboxModel.value1">
</label><br/>
<label>Value2:
<input type="checkbox" ng-model="checkboxModel.value2"
ng-true-value="'YES'" ng-false-value="'NO'">
</label><br/>
</div>
</form>
</body>
<script src="./node_modules/angular/angular.js" type="text/javascript"></script>
<script src="./node_modules/angular-sanitize/angular-sanitize.js" type="text/javascript"></script>
<script>
angular.module('app', [])
.controller('ExampleController', ['$scope', function ($scope) {
$scope.example ={
text: 'guest',
url: 'http://google.com',
email:'me@example.com',
date: new Date(2013, 9, 22),
local:new Date(2010, 11, 28, 14, 57),
time: new Date(1970, 0, 1, 14, 57, 0),
week: new Date(2013, 0, 3),
month: new Date(2013, 9, 1),
number: 12,
range:75,
min:10,
max:90
};
$scope.color = {
name: 'blue'
};
$scope.specialValue = {
"id": "12345",
"value": "green"
};
$scope.checkboxModel = {
value1 : true,
value2 : 'YES'
};
}]);
</script>
</html>
這段代碼展示了input指令支持的全部類型的基本使用方式。