当我们在 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
属性,值为 flas
e 时删除重设状态。让我们用以下示例来
演示:
<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-mode
l。需要单向数据绑定复选框,使用
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.gende
r,而是指定 otherGende
r 的变量值是 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)