4-双向数据绑定

在这一步中,我们链接了filter过滤器与orderBy过滤。动态排序由创建的一个新模型属性实现,和重复器一起写,让数据绑定魔法来实现目标。

  • 对搜索框的增加中,应用允许用户控制哪些手机用什么顺序显示在下拉列表中。

工作空间重置介绍 重置你的工作区间到第四步

git checkout -f step-4

刷新你的浏览器,或者在线上检出这一步:第四步例子 最重要的修改列在下面,你可以在 GitHub上看到全部不同。

模板

app/index.html:

Search: <input ng-model="query">
Sort by:
<select ng-model="orderProp">
  <option value="name">Alphabetical</option>
  <option value="age">Newest</option>
</select>


<ul class="phones">
  <li ng-repeat="phone in phones | filter:query | orderBy:orderProp">
    <span>{{phone.name}}</span>
    <p>{{phone.snippet}}</p>
  </li>
</ul>

我们对 index.html模板修改了如下:

  • 首先,我们增加了一个<select> html元素叫orderProp,这样我们的用户能选择两种不同的排序选项。

  • 我们链接了filter过滤器与orderBy过滤器,去进一步处理输入到重复器中,orderBy是一个这样的过滤器,他拿到一个输入数组,复制他,将拷贝重新排序,然后返回拷贝。

Angular在选择元素与 orderProp之间创建了双向数据绑定,然后 orderProp用作 orderBy过滤器的输入。 像我们在第三步中讨论的关于数据绑定与重复器一样,无论模型怎么修改,Angular的数据绑定能让视图自动地更新,不需要臃肿的DOM操作代码。

控制器

app/js/controllers.js:

var phonecatApp = angular.module('phonecatApp', []);

phonecatApp.controller('PhoneListCtrl', function ($scope) {
  $scope.phones = [
    {'name': 'Nexus S',
     'snippet': 'Fast just got faster with Nexus S.',
     'age': 1},
    {'name': 'Motorola XOOM™ with Wi-Fi',
     'snippet': 'The Next, Next Generation tablet.',
     'age': 2},
    {'name': 'MOTOROLA XOOM™',
     'snippet': 'The Next, Next Generation tablet.',
     'age': 3}
  ];

  $scope.orderProp = 'age';
});

  • 我们修改了phones模型——手机数组——并增加了一个age属性给每一条记录,这条属性是用来让手机按年龄排序。

  • 我们给控制器增加了一行,设置默认值orderProp给age,如果我们没有设置默认值,order by 过滤器将不会初始化,直到我们下拉菜单,选中一个选项。这是一个好时间去讨论双向数据绑定,注意app被浏览器加载之后,最新是被下载菜单选中,这是因为在控制器中我们设定orderProp给age,所以我们绑定工作是从我们的模型到UI,现在如果你在下拉菜单中选择了Alphabetically,模型会很好的更新,手机列表会重新排序,那就是数据绑定做了在反向方向做了他的工作,从UI到模型。

测试

这些修改必须通过我们的单元测试和端对端测试,首先让我们看单元测试 test/unit/controllersSpec.js:

describe('PhoneCat controllers', function() {

  describe('PhoneListCtrl', function(){
    var scope, ctrl;

    beforeEach(module('phonecatApp'));

    beforeEach(inject(function($controller) {
      scope = {};
      ctrl = $controller('PhoneListCtrl', {$scope:scope});
    }));

    it('should create "phones" model with 3 phones', function() {
      expect(scope.phones.length).toBe(3);
    });


    it('should set the default value of orderProp model', function() {
      expect(scope.orderProp).toBe('age');
    });
  });
});

单元测试现在测试了设置了默认值的排序 我们使用Jasmine的API去提取控制器构造器到beforeEach模块,在describe父模块中所有测试共享。 你可能在Karma选卡中看到下面的输出:

Chrome 22.0: Executed 2 of 2 SUCCESS (0.021 secs / 0.001 secs)

让我们把注意力移到端对端测试: test/e2e/scenarios.js:

...
it('should be possible to control phone order via the drop down select box', function() {

  var phoneNameColumn = element.all(by.repeater('phone in phones').column('phone.name'));
  var query = element(by.model('query'));

  function getNames() {
    return phoneNameColumn.map(function(elm) {
      return elm.getText();
    });
  }

  query.sendKeys('tablet'); //let's narrow the dataset to make the test assertions shorter

  expect(getNames()).toEqual([
    "Motorola XOOM\u2122 with Wi-Fi",
    "MOTOROLA XOOM\u2122"
  ]);

  element(by.model('orderProp')).element(by.css('option[value="name"]')).click();

  expect(getNames()).toEqual([
    "MOTOROLA XOOM\u2122",
    "Motorola XOOM\u2122 with Wi-Fi"
  ]);
});...

端对端测试验证了选择横下中的排序机制工作正常。 你可以重复运行 npm run protractor 去看测试运行。

实验

在PhoneListCtrl控制器中,移走设定orderProp值的语句,你会看到Angular暂时给下拉列表增加空白(“unknown”)选项,然后排列是无序或者自然顺序。 增加{{orderProp}}绑定到index.html模板,用文本显示当前的值。 在排序前面用一个 - 反转排列 :<option value="-age">Oldest</option>

总结

现在你已经在应用中增加了一个排序,并测试通过了。去 第5步,学习关于Angular服务,Angular怎么使用依赖注入。

转载于:https://my.oschina.net/markho/blog/498153

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值