当我们在AngularJS中处理表单,大量使用ng-model指令让数据输入输出到表单。除了数据绑定,也推荐用这种方式设计模型和绑定来简化代码。让我们看一个例子:
form组件
<html ng-app="notesApp">
<head><title>Notes App</title></head>
<body ng-controller="MainCtrl as ctrl">
<form ng-submit="ctrl.submit()">
<input type="text" ng-model="ctrl.user.username">
<input type="password" ng-model="ctrl.user.password">
<input type="submit" value="Submit">
</form>
<script src="https://cdn.jsdelivr.net/angularjs/1.2.28/angular.min.js"></script>
<script type="text/javascript">
angular.module('notesApp', [])
.controller('MainCtrl', [function() {
var self = this;
self.submit = function() {
console.log('User clicked submit with ', self.user);
};
}]);
</script>
</body>
</html>
我们仍然使用与上一次相同的两个输入字段,但我们做了一些改变:
- 我们将文本字段和按钮包裹在表单中。我们没有给按钮添加ng-click指令,而是给表单自身添加了一个ng-submit指令。作为表单按钮,ng-submit指令与ng-click指令相比有几个优势。前者可以用多种方式触发表单提交事件:单击submit按钮,或在文本字段中按回车。所有这都会触发ng-submit事件,而ng-click只有当用户单击按钮时触发。
- 我们没有绑定ctrl.username和ctrl.password,而是绑定ctrl.user.username和ctrl.user.password。注意我们并没有在控制器中声明user对象(即self.user = {})。当您使用ng-mode时,AngularJS自动创建作用域链中必需的对象和键来实例化数据绑定。在这种情况下,只有用户在用户名或密码字段输入东西,才会创建user对象。在用户名或密码字段输入第一个字母时会创建user对象,并赋值到相应的绑定字段。
文本区域
AngularJS是的文本区域与文本功能完全相同。也就是说,双向数据绑定一个文本区域,使它成为一个必填字段,只需要如下代码:
<textarea ng-model="ctrl.user.address" required>;</textarea>
所有数据绑定、错误状态,和CSS类与我们前面讲述的文本一样。
复选框
复选框是在某些方面更容易处理,因为他们只能有两个值:真或假。所以通过ng-model双向数据绑定到复选框基本上都是获取一个布尔值,基于它指定复选状态。之后,复选框任的何更改会切换模型状态:
<input type="checkbox" ng-model="ctrl.user.agree">
但是如果我们没有布尔值呢?如果我们想指定字符串YES或NO给模型,或者值为YES时选中复选框,该怎么做呢?AngularJS复选框有两个属性参数允许我们为true和false指定自定义值。我们
可用如下代码实现这个目标:
<input type="checkbox"
ng-model="ctrl.user.agree"
ng-true-value="YES"
ng-false-value="NO">
如果用户选中复选框,这个agree字段的值设置为YES,如果没有选中设置为NO。
但是,如果我们不想使用双向数据绑定,只想用复选框显示当前值的布尔值?也就是说,单向数据绑定意味着值变化时会改变复选框状态,但复选框状态变化时值不会改变。
我们可以使用ng-checked这个指令来实现,将它绑定到一个AngularJS表达式。只要值为true,AngularJS将为输入元素设置checked属性,值为flase时删除重设状态。让我们用以下示例来
演示:
<html ng-app="notesApp">
<head><title>Notes App</title></head>
<body ng-controller="MainCtrl as ctrl">
<div>
<h2>What are your favorite sports?</h2>
<div ng-repeat="sport in ctrl.sports">
<label ng-bind="sport.label"></label>
<div>
With Binding:
<input type="checkbox"
ng-model="sport.selected"
ng-true-value="'YES'"
ng-false-value="'NO'">
</div>
<div>
Using ng-checked:
<input type="checkbox"
ng-checked="sport.selected === 'YES'">
</div>
<div>
Current state: {{sport.selected}}
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/angularjs/1.2.28/angular.min.js"></script>
<script type="text/javascript">
angular.module('notesApp', [])
.controller('MainCtrl', [function() {
var self = this;
self.sports = [
{label: 'Basketball', selected: 'YES'},
{label: 'Cricket', selected: 'NO'},
{label: 'Soccer', selected: 'NO'},
{label: 'Swimming', selected: 'YES'}
];
}]);
</script>
</body>
</html>
在这个例子中,我们使用了ng-repeat,它有一个带有ng-model属性的复选框,和有一个带有ng-checked属性的复选框,一个div绑定当前状态。第一个复选框通过ng-model指令使用传统的双向数据绑定。第二个使用ng-checked。这意味着:
- 当用户选中第一个复选框,selected的值变成YES,因为true值使用ng-trueee-value属性设置成YES。这会触发ng-checked并设置第二项选中(或取消选定)。
- 当用户取消第一个框,因为ng-false-value属性selected的值设置成NO。
- 每个repeater元素中的第二个复选框使用ng-checked显示ng-model的状态。无论模型支持的ng-model何时变化,都会更新该复选框的状态。选中或勾选第二个复选框不会影响模型的值。
所以如果您需要双向数据绑定复选框,使用ng-model。需要单向数据绑定复选框,使用ng-checked。
单选按钮
单选按钮的行为类似于复选框,但略有不同。您可以拥有多个单选按钮(如您通常做的),取决于哪一个被选中每个按钮赋不同的值给模型。您可以使用传统的输入元素的value属性值指定该值。让我们看看下面例子:
<div ng-init="otherGender = 'other'">
<input type="radio"
name="gender"
ng-model="user.gender"
value="male">Male
<input type="radio"
name="gender"
ng-model="user.gender"
value="female">Female
<input type="radio"
name="gender"
ng-model="user.gender"
ng-value="otherGender">{{otherGender}}
</div>
在这个例子中,有两个。我们给他们相同的名称以便选中一个按钮时,取消选定另一个按钮。他们都绑定到同一个ng-model(user.gender)
上。接下来,每个单选按钮都有一个值,它的值保存在user.gender中。(第一个单选按钮男性,否则表示女性)。最后,外层有一个ng-init块,默认情况下设置user.gender的值为女性。这样做可以确保当这个片段的HTML加载后第二个复选框被选中。
但是如果我们的值是动态的呢?如果我们需要分配的值是放置在控制器,还是其他地方呢?为此,AngularJS提供ng-value属性,它可以单独与单选按钮使用。ng-value使用AngularJS表达式,将表达式返回值指定给模型值:
<div ng-init="otherGender = 'other'">
<input type="radio"
name="gender"
ng-model="user.gender"
value="male">Male
<input type="radio"
name="gender"
ng-model="user.gender"
value="female">Female
<input type="radio"
name="gender"
ng-model="user.gender"
ng-value="otherGender">{{otherGender}}
</div>
在这个例子中,第三个单选按钮使用了动态值。我们指定它为初始化块(ng-init)的一部分。但在实际的应用中,初始化在控制器中进行,而不是直接在HTML里面。我们设置ng-value = "otherGender",
并不是将otherGender作为字符串指定给user.gender,而是指定otherGender的变量值是other。
列表/菜单
最后我们将介绍HTML表单元素(可以使用外部表单):选择框或大家都知道的组合下拉框。让我们使用最简单的方式来看一看AngularJS中怎样选择使用选择框:
<div ng-init="location = 'China'">
<select ng-model="location">
<option value="USA">USA</option>
<option value="China">China</option>
<option value="Other">None of the above</option>
</select>
</div>
在这个例子中,有一个简单的选择框,数据绑定到变量location。我们还初始化location的值为中国,所以当HTML加载,中国是默认的选项。当用户选择其他选项时,value属性值指定给ng-
model。标准的验证器和状态也适用于这个字段,比如required等。不过也有一些限制:
- 您需要知道下拉中的值。
- 他们需要硬编码。
- 值只能是字符串。
在一个真正的动态应用程序,可能存在一个或所有限制。在这种情况下,选择HTML元素也有一种动态生成的列表选项,通过ng-models对象而不是纯粹的字符串来完成。这是通过ng-options指
令。让我们来看看这是如何工作的:
<html ng-app="notesApp">
<head><title>Notes App</title></head>
<body ng-controller="MainCtrl as ctrl">
<div>
<select ng-model="ctrl.selectedCountryId"
ng-options="c.id as c.label for c in ctrl.countries">
</select>
Selected Country ID : {{ctrl.selectedCountryId}}
</div>
<div>
<select ng-model="ctrl.selectedCountry"
ng-options="c.label for c in ctrl.countries">
</select>
Selected Country : {{ctrl.selectedCountry}}
</div>
<script src="https://cdn.jsdelivr.net/angularjs/1.2.28/angular.min.js"></script>
<script type="text/javascript">
angular.module('notesApp', [])
.controller('MainCtrl', [function() {
this.countries = [
{label: 'USA', id: 1},
{label: 'China', id: 2},
{label: 'Other', id: 3}
];
this.selectedCountryId = 2;
this.selectedCountry = this.countries[1];
}]);
</script>
</body>
</html>
在这个例子中,我们有两个选择框,都绑定到不同的控制器模型。第一个绑定ctrl.selectedCountryId元素,第二个是绑定到ctrl.selectedCountry。请注意,第一个值是一个数字,而另
一个是一个实际的对象。我们如何实现这一目标?
- 我们使用ng-options属性选择对话框,它允许我们重复一个数组(或对象)和动态显示选项。
- 语法也类似于ng-repeat,另外还能选择显示什么为标签,绑定什么到模型。
- 在第一个选择框中,
ng-options = "c.id as c.label for c in ctrl.countries”
。AngularJS会为国家数组中每个国家创建一个选项。语法如下:模型值 as 标签值 for item in array。在本实例中,AngularJS模型值是每个元素ID值,标签值是每个数组项的模型键,然后通常使用each循环。 - 在第二个选择框中,设置
ng-options = "c.label for c in ctrl.countries”
。在这里,当我们省略了模型值,AngularJS假定repeat中的每个项目是实际的模型值,所以当我们从第二个选择框点击一个选项时,该国的对象(c)被指定给ctrl.selectedCountry。 - 因为两个选择框的支持模型不同,改变一个不影响中一个值或另一个下拉的选择。
- 您还可以选择性使用分组语句,语法:
ngoptions=“modelValue as labelValue group by groupValue for item in array”
。类似于我们如何指定模型值和标签值,我们可以将groupValue指定为对象的另一个键(比如说continent)。 - 使用对象时,语句修改如下:modelValue as labelValue group by groupValue for (key, value) in object。
评论 (0)