使用 AngulaerJS 表单

Flying
2015-01-02 / 0 评论 / 117 阅读 / 正在检测是否收录...

当我们在 AngularJS 中处理表单,大量使用 ng-model 指令让数据输入输出到表单。除了数据绑定,也推荐用这种方式设计模型和绑定来简化代码。让我们看一个例子:

form-angular.svg

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.usernamectrl.password,而是绑定 ctrl.user.usernamectrl.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">

但是如果我们没有布尔值呢?如果我们想指定字符串 YESNO 给模型,或者值为 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
4

评论 (0)

取消