英雄指南——英雄编辑器

版本:v4.0.0+2

在教程的这一部分,你将修改启动程序来显示一个英雄的信息。然后你间添加编辑英雄数据的能力。完成后,应用看起来这样——在线示例 (查看源码)。

回顾上一章

在开始编写代码之前,让我们验证你是否有如下的文件结构。如果没有,回到前一章,查看详细介绍。

如果应用不运行了,启动应用。当你做出修改时,通过刷新浏览器保持继续运行。

显示英雄

AppComponent添加两个属性:一个表示应用名字的title属性,和一个表示名为 “Windstorm” 的英雄的hero 属性。

// lib/app_component.dart (AppComponent class)

class AppComponent {
  final title = 'Tour of Heroes';
  var hero = 'Windstorm';
}

现在,使用数据绑定到这些新属性,更新@Component注解中的模板。

// lib/app_component.dart (@Component)

template: '<h1>{{title}}</h1><h2>{{hero}} details!</h2>',

刷新浏览器,页面将显示标题和英雄名字。

双大括号是 Angular 的插值表达式语法。这些插值绑定组件的titlehero属性值,作为字符串,插入到 HTML 的标题标签中。

更多关于插值表达式的内容请看显示数据章节。

创建 Hero

英雄需要更多属性。把hero从一个字符串字面量转换成一个类。

创建一个具有 idname 属性的Hero 类。把这些属性添加到 app_component.dart文件的顶部附近,仅在 import 语句下面。

// lib/app_component.dart (Hero class)

class Hero {
  final int id;
  String name;

  Hero(this.id, this.name);
}

AppComponent类,重构组件的 hero 属性为 Hero 类型,然后以id1、以name为 “Windstorm”,初始化它。

// lib/app_component.dart (hero property)

Hero hero = new Hero(1, 'Windstorm');

因为我们把 hero 从一个字符串换成了对象,所以更新模板中的绑定,来引用 hero 的name属性。

template: '<h1>{{title}}</h1><h2>{{hero.name}} details!</h2>',

刷新浏览器,页面将继续显示英雄的名字。

添加多行 HTML 模板

为了显示英雄的所有属性,添加一个<div>来显示英雄的id属性,另一个<div>来显示英雄的name属性。为了使模板保持可读性,每个div独自占一行。

// lib/app_component.dart (multi-line strings)

template: '''
  <h1>{{title}}</h1>
  <h2>{{hero.name}} details!</h2>
  <div><label>id: </label>{{hero.id}}</div>
  <div><label>name: </label>{{hero.name}}</div>
''',

使应用名字可编辑

用户应该能够在一个<input>文本框中编辑英雄名字。文本框应该既能显示 应用的name属性,又能根据用户的输入更新 属性。

你需要在<input>表单元素和hero.name属性之间双向数据绑定。

使用双向绑定

重构模板中的英雄名字使其看起来如下:

<div>
  <label>name: </label>
  <input [(ngModel)]="hero.name" placeholder="name">
</div>

[(ngModel)]是 Angular 语法,绑定hero.name属性到文本框。数据在两个方向流动:从属性到文本框,从文本框又回到属性。

查看 ngModel 更多信息在表单模板语法

声明非核心指令

不幸的是,这样改变之后,程序立即崩溃了!

模板解析错误

如果你刷新浏览器,应用不会加载。要知道原因,查看pub serve输出。模板解析器不能识别ngModelAppComponent解析错误:

 Error running TemplateGenerator for forms|lib/src/hero_form_component.dart.
  Error: Template parse errors:
  Can't bind to 'ngModel' since it isn't a known native property or known directive. Please fix typo or add to directives list.
  [(ngModel)]="hero.name"
  ^^^^^^^^^^^^^^^^^^^^^^^

更新 pubspec

angular_forms库包含在它自己的包里。在 pubsepc dependencies中添加包:

// {toh-0 → toh-1}/pubspec.yaml

dependencies:
    angular: ^4.0.0
+  angular_forms: ^1.0.0

更新 @Component(directives:...)

尽管NgModelangular_forms库中是一个有效的 Angular 指令,但默认它不是可用的。

在模板中使用任意 Angular 指令之前,需要在组件的@Component注解的directives参数中列出它们。你可以单独的添加指令,或为了方便添加formDirectives列表(注意新的导入语句):

// lib/app_component.dart (directives)

import 'package:angular_forms/angular_forms.dart';

@Component(
  selector: 'my-app',
  // ···
  directives: const [formDirectives],
)

刷新浏览器,应用应该可用再次运行了。你可以编辑英雄名字并且在文本框上方的<h2>中立刻看到变化的反应。

你已走过的路

来盘点一下都构建了哪些内容。

  • 英雄指南应用使用双大括号插值表达式(单向数据绑定的一种形式)来显示应用的标题和Hero对象的属性。
  • 使用 Dart 模板字符串写了一个多行模板,使模板更有可读性。
  • 使用内置的ngModel指令为<input>元素添加双向数据绑定。这种绑定既可以显示英雄的名字又允许用户修改它。
  • 添加formDirectives到应用的@Component注解的directives参数,以使 Angular 知道ngModel是在哪里定义i的。

你的应用看起来应该这样——在线示例 (查看源码)

完整的app_component.dart是这样的:

// lib/app_component.dart

import 'package:angular/angular.dart';
import 'package:angular_forms/angular_forms.dart';
@Component(
  selector: 'my-app',
  template: '''
    <h1>{{title}}</h1>
    <h2>{{hero.name}} details!</h2>
    <div><label>id: </label>{{hero.id}}</div>
    <div>
      <label>name: </label>
      <input [(ngModel)]="hero.name" placeholder="name">
    </div>
  ''',
  directives: const [formDirectives],
)
class AppComponent {
  final title = 'Tour of Heroes';
  Hero hero = new Hero(1, 'Windstorm');
}
class Hero {
  final int id;
  String name;
  Hero(this.id, this.name);
}

下一步

主从结构

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容

  • 版本:4.0.0+2 有一些英雄指南应用的新需求: 添加一个仪表盘 视图。 添加在英雄 视图和 仪表盘 视图之间导...
    soojade阅读 1,290评论 0 0
  • 版本:v4.0.0+2 在这一章,你将扩展英雄指南应用来显示一列英雄,并允许用户来选择一个英雄,同时显示这个英雄的...
    soojade阅读 538评论 0 1
  • 版本:4.0.0+2 在本章,你会做以下改进。 从一个服务器获取英雄数据。 让用户添加、编辑和删除英雄。 保存改变...
    soojade阅读 991评论 0 3
  • 版本:Angular 5.0.0-alpha 表单是商业应用的支柱,我们用它来执行登录、求助、下单、预订机票、安排...
    soojade阅读 1,276评论 0 1
  • passX19A阅读 177评论 0 0