其它AngularJS表单组件

我们已经讲解过表单、ng-models和绑定,但大多数情况下我们不仅仅只使用常见的文本框。让我们看一下AngularJS中其他表单元素是如何互动和工作的。

文本区域

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="http://riafan.com/libs/angular.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="http://riafan.com/libs/angular.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。

不完全译自《AngularJS-Up and Running》。

发表评论