LieBrother

当才华撑不起野心时,应该静下心来学习;当能力驾驭不了目标时,应该沉下心来历练。


  • 首页

  • 归档

  • 分类

  • 标签

  • 关于

Angular 的响应式表单

发表于 2017-08-03   |   分类于 Angular , James-Blog   |     |   阅读次数

摘要:本文简单介绍 Angular 的响应式表单,还是以之前的评论模块为例

介绍

Angular 总共提供了 3 中表单实现方式,分别是:Template-driven Forms (模板驱动表单)、 Reactive Forms (响应式表单)、Dynamic Forms (动态表单)。本文只介绍响应式表单。

响应式表单是什么呢?其实跟我们以前用 JQuery 或者其他框架实现的思路差不多,就是使用 HTML 显示数据,然后通过定义一定的校验器、校验规则以及校验提示语,通过事件触发校验后校验不通过的显示提示语,只不过用了 Angular,我们就使用 Angular 提供的语法来实现这个校验过程。

使用

接下来我们通过代码例子来介绍如何使用响应式表单。

引入响应式表单模块

在我们要使用响应式表单的那个模块里面引入响应式表单模块,比如我们在文章模块中使用响应式表单,我们就要在 imports 中添加 ReactiveFormsModule。代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@NgModule({
imports: [
RouterModule,
RouterModule.forChild(articleRoutes),
SharedModule,
ReactiveFormsModule,
NgbModule.forRoot()
],
declarations: [
HomeComponent,
DetailComponent,
CommentComponent,
CommentViewComponent
],
providers: [
HomeService,
DetailService,
CommentService
]
})
export class ArticleModule { }

编写校验器代码

首先我们这里的表单有 3 个字段,分别是 nickname、email、content; nickname 添加必填校验器,email 添加必填和邮箱格式校验器,content添加必填校验器。

首先在 CommentComponent 中注入 FormBuilder 对象,并添加 commentForm 表单组以及创建一个评论对象 comment。

1
2
3
4
public commentForm: FormGroup;
public comment: Comment = new Comment();

constructor(private formBuilder: FormBuilder){}

定义校验器的提示语 validationMessages, formErrors 是在模板中显示的提示语,提示语来自 validationMessages

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public formErrors = {
"nickname": "",
"email": "",
"content": "",
"formError": ""
}

public validationMessages = {
"nickname": {
"required": "昵称不能为空",
},
"email": {
"required": "邮箱不能为空",
"pattern": "请输入正确的邮箱地址"
},
"content": {
"required": "内容不能为空"
}
}

在组件启动的函数中构造表单,这时候为每个字段添加了校验器,并且绑定在什么时候触发校验,这里我们在每个值改变的时候触发。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
ngOnInit(): void {
this.buildForm();
}

private buildForm() {
this.commentForm = this.formBuilder.group({
"nickname":[
this.comment.nickname,
[
Validators.required
]
],
"email": [
this.comment.email,
[
Validators.required,
Validators.pattern("^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$")
]
],
"content": [
this.comment.content,
[
Validators.required
]
]
});
this.commentForm.valueChanges.subscribe(data => this.onValueChanged(data));
this.onValueChanged();
}

onValueChanged() 方法实现了判断是那个字段校验不通过,然后将该字段的 validationMessages 提示语赋值给 formErrors,在模板那里有判断如果 formErrors.email 等等字段不为空则显示改内容,也即是校验器的提示语

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
onValueChanged(data?: any) {
if (!this.commentForm) {
return;
}
const form = this.commentForm;
for (const field in this.formErrors) {
this.formErrors[field] = '';
const control = form.get(field);
if (control && control.dirty && !control.valid) {
const messages = this.validationMessages[field];
for (const key in control.errors) {
this.formErrors[field] += messages[key] + ' ';
}
}
}

}

HTML 模板代码

我们要关注的是 [formGroup]=”commentForm”、novalidate、formControlName=”nickname”、以及 *ngIf=”formErrors.nickname” 这几个点,并不是指具体的点,而是着重看这些语法的每一个地方,在你自己实现的时候需要根据你的代码修改的。
还有一个是 (ngSubmit)=”sendComment()” 定义了该表单点击提交时调用的函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<form [formGroup]="commentForm" (ngSubmit)="sendComment()" role="form" novalidate>
<div class="control-group">
<div class="form-group floating-label-form-group controls" [ngClass]="{'has-error': formErrors.nickname}">
<label>{{ 'comment.nickname' | translate }}</label>
<input formControlName="nickname" type="text" class="form-control" placeholder="{{ 'comment.nickname' | translate }}">
<p *ngIf="formErrors.nickname" class="help-block text-danger">
{{ formErrors.nickname }}
</p>
</div>
</div>
<div class="control-group" >
<div class="form-group floating-label-form-group controls" [ngClass]="{'has-error': formErrors.email}">
<label>{{ 'comment.email' | translate }}</label>
<input formControlName="email" type="email" class="form-control" placeholder="{{ 'comment.email' | translate }}">
<p *ngIf="formErrors.email" class="help-block text-danger">
{{ formErrors.email }}
</p>
</div>
</div>
<div class="control-group">
<div class="form-group floating-label-form-group controls" [ngClass]="{'has-error': formErrors.content}">
<label>{{ 'comment.content' | translate }}</label>
<textarea formControlName="content" rows="5" class="form-control" placeholder="{{ 'comment.content' | translate }}"></textarea>
<p *ngIf="formErrors.content" class="help-block text-danger">
{{ formErrors.content }}
</p>
</div>
</div>
<p *ngIf="formErrors.formError" class="help-block text-danger">
{{ formErrors.formError }}
</p>
<br>
<div id="success"></div>
<div class="form-group">
<button [disabled]="commentForm.invalid" type="submit" class="btn btn-secondary" >{{ 'comment.submit' | translate }}</button>
</div>
</form>

GitHub 代码

James-Blog 中的 comment.component.ts 文件

参考文章

Reactive Forms

效果图

angular-reactive-forms.png

Angular 实现类似博客获取回复评论的数据

发表于 2017-08-01   |   分类于 Angular , James-Blog   |     |   阅读次数

摘要:本文继上一篇文章 Angular 实现类似博客评论的递归显示 讲述的内容,上篇文章里面只是说明了如何实现评论梯形显示,在博客评论中我们经常看到可以回复某一条评论,本文讲述如何实现点击某一条评论的回复按钮后,获取该条评论的内容并显示在输入框中。类似 CSDN 博客评论一样,点击回复后输入框自动添加了 [reply]u011642663[/reply]

思路

依据上一篇文章中的评论梯形显示,我们还需要实现点击回复后,屏幕自动到达输入框位置,并且获取了点击回复的评论的信息。首先分解一下这个功能点,在项目中我们也会经常分解功能点,这个功能点有 2 个小点:一是在每条评论中加上 [回复] 按钮,点击回复后跳到输入框位置;二是点击回复后,获取到点击回复的那条评论的信息。下面我们一一解决。

跳转到输入框

我们接触前段第一个语言便是 HTML,我们知道 HTML 中有一个 # 定位,下面代码简单解释一下。
假设这个 HTML 代码文件是 index.html

1
2
3
4
5
6
7
8
9
10
<html>
<head>
</head>
<body>
<a href="index.html#pointer">Click me to pointer</a>
<div id="pointer">
<h1>哈哈哈哈</h1>
</div>
</body>
</html>

上面代码只要点击 Click me to pointer 这个链接,页面就会跳到 id=”pointer” 这个 div 的位置。所以我们在实现这个点击回复跳转到输入框中就可以使用这个方法。
我们在 comment-component.html 中将评论输入框加入 id=”comment”,接下来就是路径拼接的问题了,我们可以通过 Angular 的 Router 的 url 来获取本页面的路径,然后在这个路径后面加入 #comment 就可以实现跳转了,下面是实现这个跳转功能的代码

添加 id=”comment”

comment-component.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- Comment -->
<div class="container font-small">
<div class="row">
<div class="col-lg-8 offset-lg-2 col-md-10 offset-md-1">

<comment-view [comments]="comments" (contentEvent)="getReplyComment($event)" ></comment-view>

<div class="well" id="comment">
<h4>{{ 'comment.leaveComment' | translate }}</h4>
<form role="form">
<div class="form-group">
<input type="hidden" [(ngModel)]="id" name="id">
<textarea [(ngModel)]="content" name="content" class="form-control" rows="5"></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
</div>

添加通过路由获取当前页面 URL

comment-view.component.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Component({
selector: 'comment-view',
templateUrl: './comment-view.component.html',
styleUrls: ['./comment-view.component.css']
})
export class CommentViewComponent implements OnInit {
@Input()
public comments: Comment[];

// 用于跳转到回复输入框的url拼接
public url: string = "";

constructor(private router: Router,
private activateRoute: ActivatedRoute ) {
}

ngOnInit(): void {
this.url = this.router.url;
this.url = this.url.split("#")[0];
this.url = this.url + "#comment";
}
}

添加链接 href=”“

comment-view.component.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div *ngFor="let comment of comments">
<div class="media">
<div class="pull-left">
<span class="media-object"></span>
</div>
<div class="media-body">
<h4 class="media-heading">{{ comment.username }}
<small class="pull-right">{{ comment.time }}&nbsp;|&nbsp;<a href="{{url}}" (click)="reply(comment)" >{{ 'comment.reply' | translate }}</a></small>
</h4>
{{ comment.content }}
<hr>
<comment-view *ngIf="comment.cComments != null" [comments]="comment.cComments" (contentEvent)="transferToParent($event)"></comment-view>
</div>
</div>
</div>

这就实现了页面跳转的功能点,接下来实现获取回复的评论的信息。

获取回复的评论信息

有人会说获取回复的评论信息,这不简单么?加个 click 事件不就行了。还记得上一篇文章咱们是如何实现梯形展示评论的么?咱们是通过递归来实现的,怎么添加 click 事件让一个不知道嵌了多少层的组件能够把评论信息传给父组件?首先不具体想怎么实现,我们这个思路是不是对的:把子组件的信息传给父组件?答案是肯定的,我们就是要把不管嵌了多少层的子组件的信息传给 comment.component.ts 这个评论模块的主组件。
Angular 提供了 @Output 来实现子组件向父组件传递信息,我们在 comment-view.component.ts 模块中添加 @Output 向每个调用它的父组件传信息,我们是嵌套的,这样一层一层传出来,直到传给 comment-component.ts 组件。我们看代码怎么实现。

实现代码

comment-view.component.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Component({
selector: 'comment-view',
templateUrl: './comment-view.component.html',
styleUrls: ['./comment-view.component.css']
})
export class CommentViewComponent implements OnInit {
@Input()
public comments: Comment[];
// 点击回复时返回数据
@Output()
public contentEvent: EventEmitter<Comment> = new EventEmitter<Comment>();
// 用于跳转到回复输入框的url拼接
public url: string = "";

constructor(private router: Router,
private activateRoute: ActivatedRoute ) {
}

ngOnInit(): void {
this.url = this.router.url;
this.url = this.url.split("#")[0];
this.url = this.url + "#comment";
}

reply(comment: Comment) {
this.contentEvent.emit(comment);
}

transferToParent(event) {
this.contentEvent.emit(event);
}
}

comment-view.component.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div *ngFor="let comment of comments">
<div class="media">
<div class="pull-left">
<span class="media-object"></span>
</div>
<div class="media-body">
<h4 class="media-heading">{{ comment.username }}
<small class="pull-right">{{ comment.time }}&nbsp;|&nbsp;<a href="{{url}}" (click)="reply(comment)" >{{ 'comment.reply' | translate }}</a></small>
</h4>
{{ comment.content }}
<hr>
<comment-view *ngIf="comment.cComments != null" [comments]="comment.cComments" (contentEvent)="transferToParent($event)"></comment-view>
</div>
</div>
</div>

comment.component.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Component({
selector: 'comment',
templateUrl: './comment.component.html',
styleUrls: ['./comment.component.css']
})
export class CommentComponent implements OnInit {

@Input()
public comments: Comment[];

// 要回复的评论
public replyComment: Comment = new Comment();

public id: number = 0;
public content: string = "";

ngOnInit(): void {
}

getReplyComment(event) {
this.replyComment = event;
this.id = this.replyComment.id;
this.content = "[reply]" + this.replyComment.username + "[reply]\n";
}
}

comment.component.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- Comment -->
<div class="container font-small">
<div class="row">
<div class="col-lg-8 offset-lg-2 col-md-10 offset-md-1">

<comment-view [comments]="comments" (contentEvent)="getReplyComment($event)" ></comment-view>

<div class="well" id="comment">
<h4>{{ 'comment.leaveComment' | translate }}</h4>
<form role="form">
<div class="form-group">
<input type="hidden" [(ngModel)]="id" name="id">
<textarea [(ngModel)]="content" name="content" class="form-control" rows="5"></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
</div>

解释一下代码逻辑:
我们在 comment-view.component.ts 添加以下几点:

  1. 定义了@Output() contentEvent
  2. 添加了reply(comment: Comment) 事件在点击回复的时候触发的,触发的时候 contentEvent 将 comment 传到父模块
  3. 添加 transferToParent(event) 是接受子组件传来的 event, 并且继续将 event 传到父组件

在 comment.component.ts 中定义了 getReplyComment(event) 方法,该方法接收子组件传递来的评论信息,并将信息显示在页面上。大功告成。。。

效果图

angular-comment-recursive-event.png

demo 代码

James-Blog

Angular 实现类似博客评论的递归显示

发表于 2017-07-31   |   分类于 Angular , James-Blog   |     |   阅读次数

摘要:本文讲述用 Angular4 来实现一般博客中经常看到的递归评论模块

我们在一些技术博客中会经常看到很多递归评论,也即是我们可以回复博友的评论,且界面很美观,有梯度的显示格式,日前在空余时间写类似的 demo,所以记录下来,可以给需要的人一些借鉴的作用。
好了,废话少说,直奔主题。。。

思路

我们在写后台程序的时候,经常会遇到生成类似树的这种数据结构,我们直觉就是使用递归的方法来实现,起初我也是这么想的,就是写一个 Angular4 的递归方法,组成一个字符串,然后在界面显示,类似下面代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Component({
selector: "comment",
template: '{{ comments }}'
})
export class CommentComponent {

public comments: string = "";

generateComment(Comment comment) {
this.comments = this.comments + "<div>" + comment.content + "</div>";
if (comment.pComment != null) {
generateComment(comment.pComment);
}
}
}

很天真的以为可以了,结果一试,标签不会被解析,才想起已经过了解析标签的过程了。。。

后来想着,现在的前端框架都是以组件化自称, Angular4 也不例外,那么一个 Component 可以嵌入任何 Component,那肯定可以嵌入自己,也就有了类似递归的概念了,想到这立马试试。。。

具体实现

思路是这样子,我定义了数据的格式,是每个评论下面有一个子评论数组,而不是每个评论有一个父评论,数据格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
"comments": 
[
{
"id": 1,
"username": "James1",
"time": "2017-07-09 21:02:21",
"content": "哈哈哈1<h1>哈哈哈</h1>",
"status": 1,
"email": "1xxxx@xx.com",
"cComments": [
{
"id": 2,
"username": "James2",
"time": "2017-07-09 21:02:22",
"content": "哈哈哈2",
"status": 1,
"email": "2xxxx@xx.com",
"cComments": null
}
]
}
]

CommentComponent 组件实现了评论模块,但是递归评论并不在这个组件实现,而是在子组件 CommentViewComponent 实现,因为 CommentComponent 还包括一个一个输入评论的文本框。

评论总模块 ComponentComponent 代码:

comment.component.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
@Component({
selector: 'comment',
templateUrl: './comment.component.html',
styleUrls: ['./comment.component.css']
})
export class CommentComponent implements OnInit {

@Input()
public comments: Comment[];

ngOnInit(): void {
}
}

comment.component.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div class="container font-small">
<div class="row">
<div class="col-lg-8 offset-lg-2 col-md-10 offset-md-1">

<comment-view [comments]="comments"></comment-view>

<div class="well" id="comment">
<h4>{{ 'comment.leaveComment' | translate }}</h4>
<form role="form">
<div class="form-group">
<input type="hidden" [(ngModel)]="id" name="id">
<textarea [(ngModel)]="content" name="content" class="form-control" rows="5"></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
</div>

comment.component.css

1
2
3
4
5
6
7
.media {
font-size: 14px;
}

.media-object {
padding-left: 10px;
}

子模块 ComponentViewComponent 代码:

component-view.component.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Component({
selector: 'comment-view',
templateUrl: './comment-view.component.html',
styleUrls: ['./comment-view.component.css']
})
export class CommentViewComponent implements OnInit {
@Input()
public comments: Comment[];

constructor(private router: Router,
private activateRoute: ActivatedRoute ) {
}

ngOnInit(): void {
}
}

component-view.component.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div *ngFor="let comment of comments">
<div class="media">
<div class="pull-left">
<span class="media-object"></span>
</div>
<div class="media-body">
<h4 class="media-heading">{{ comment.username }}
<small class="pull-right">{{ comment.time }}&nbsp;|&nbsp;<a href="#" >{{ 'comment.reply' | translate }}</a></small>
</h4>
{{ comment.content }}
<hr>
<comment-view *ngIf="comment.cComments != null" [comments]="comment.cComments"></comment-view>
</div>
</div>
</div>

comonent-view.component.css

1
2
3
4
5
6
7
.media {
font-size: 14px;
}

.media-object {
padding-left: 10px;
}

结果

这时的展示结果如下图所示:

angular-comment-recursive-display.png

在 Angular 项目中添加 clean-blog 模板

发表于 2017-07-03   |   分类于 Angular , James-Blog   |     |   阅读次数

摘要:本文将介绍在 Angular4 项目中添加网上开源 Bootstrap 博客模板 clean-blog

clean-blog 博客模板下载

clean-blog
或者在下面链接下载
startbootstrap-clean-blog-4-dev.zip

解压并拷贝

解压下载的文件,将所有文件拷贝到 assets/clean-blog 目录下
angular-add-clean-blog-template-1.png

拷贝代码

将 clean-blog 的 index.html 内容拷贝到 app.component.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<!--The whole content below can be removed with the new code.-->

<!-- Navigation -->
<nav class="navbar fixed-top navbar-toggleable-md navbar-light" id="mainNav">
<div class="container">
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse"
data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false"
aria-label="Toggle navigation">
Menu <i class="fa fa-bars"></i>
</button>
<a class="navbar-brand" href="index.html">Start Bootstrap</a>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" href="index.html">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="../assets/clean-blog/about.html">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="../assets/clean-blog/post.html">Sample Post</a>
</li>
<li class="nav-item">
<a class="nav-link" href="../assets/clean-blog/contact.html">Contact</a>
</li>
</ul>
</div>
</div>
</nav>

<!-- Page Header -->
<header class="masthead" style="background-image: url('../assets/clean-blog/img/home-bg.jpg')">
<div class="container">
<div class="row">
<div class="col-lg-8 offset-lg-2 col-md-10 offset-md-1">
<div class="site-heading">
<h1>Clean Blog</h1>
<span class="subheading">A Blog Theme by Start Bootstrap</span>
</div>
</div>
</div>
</div>
</header>

<!-- Main Content -->
<div class="container">
<div class="row">
<div class="col-lg-8 offset-lg-2 col-md-10 offset-md-1">
<div class="post-preview">
<a href="../assets/clean-blog/post.html">
<h2 class="post-title">
Man must explore, and this is exploration at its greatest
</h2>
<h3 class="post-subtitle">
Problems look mighty small from 150 miles up
</h3>
</a>
<p class="post-meta">Posted by <a href="#">Start Bootstrap</a> on September 24, 2017</p>
</div>
<hr>
<div class="post-preview">
<a href="../assets/clean-blog/post.html">
<h2 class="post-title">
I believe every human has a finite number of heartbeats. I don't intend to waste any of mine.
</h2>
</a>
<p class="post-meta">Posted by <a href="#">Start Bootstrap</a> on September 18, 2017</p>
</div>
<hr>
<div class="post-preview">
<a href="../assets/clean-blog/post.html">
<h2 class="post-title">
Science has not yet mastered prophecy
</h2>
<h3 class="post-subtitle">
We predict too much for the next year and yet far too little for the next ten.
</h3>
</a>
<p class="post-meta">Posted by <a href="#">Start Bootstrap</a> on August 24, 2017</p>
</div>
<hr>
<div class="post-preview">
<a href="../assets/clean-blog/post.html">
<h2 class="post-title">
Failure is not an option
</h2>
<h3 class="post-subtitle">
Many say exploration is part of our destiny, but it’s actually our duty to future generations.
</h3>
</a>
<p class="post-meta">Posted by <a href="#">Start Bootstrap</a> on July 8, 2017</p>
</div>
<hr>
<!-- Pager -->
<div class="clearfix">
<a class="btn btn-secondary float-right" href="#">Older Posts &rarr;</a>
</div>
</div>
</div>
</div>

<hr>

<!-- Footer -->
<footer>
<div class="container">
<div class="row">
<div class="col-lg-8 offset-lg-2 col-md-10 offset-md-1">
<ul class="list-inline text-center">
<li class="list-inline-item">
<a href="#">
<span class="fa-stack fa-lg">
<i class="fa fa-circle fa-stack-2x"></i>
<i class="fa fa-twitter fa-stack-1x fa-inverse"></i>
</span>
</a>
</li>
<li class="list-inline-item">
<a href="#">
<span class="fa-stack fa-lg">
<i class="fa fa-circle fa-stack-2x"></i>
<i class="fa fa-facebook fa-stack-1x fa-inverse"></i>
</span>
</a>
</li>
<li class="list-inline-item">
<a href="#">
<span class="fa-stack fa-lg">
<i class="fa fa-circle fa-stack-2x"></i>
<i class="fa fa-github fa-stack-1x fa-inverse"></i>
</span>
</a>
</li>
</ul>
<p class="copyright text-muted">Copyright &copy; Your Website 2017</p>
</div>
</div>
</div>
</footer>

styles.css 添加代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* clean-blog */
@import "assets/clean-blog/vendor/font-awesome/css/font-awesome.min.css";
@import "https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic";
@import "https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800";
@import "assets/clean-blog/css/clean-blog.min.css";

.navbar-toggler {
z-index: 1;
}

@media (max-width: 576px) {
nav > .container {
width: 100%;
}
}

index.html 添加 JS 引用

1
2
<!-- clean-blog -->
<script src="assets/clean-blog/js/clean-blog.min.js"></script>

结果

angular-add-clean-blog-template-2.png

提示: 文中的配置只是把 clean-blog 给搭建在 Angular4 的项目中,但是并没有大改其中的东西,比如链接等,现在还是一个静态的网页,后期才会添加自己的代码上去

示例代码

angular + clean-blog

在 Angular 项目中添加插件 ng-bootstrap

发表于 2017-07-02   |   分类于 Angular , James-Blog , ng-bootstrap   |     |   阅读次数

摘要:本文将介绍在 Angular4 项目中配置 ng-bootstrap

npm 安装 ng-bootstrap 模块

1
npm install @ng-bootstrap/ng-bootstrap --save

在 Angular 项目配置

app.module.ts

添加

1
2
3
4
5
6
7
8
import { NgbModule } from "@ng-bootstrap/ng-bootstrap";

imports: [
/**
* ngx-bootstrap
*/
NgbModule.forRoot()
],

添加 bootstrap.min.css 样式

在 assets 文件夹下 bootstrap/bootstrap.min.css , 并在 style.css 文件中添加

1
@import "assets/bootstrap/bootstrap.min.css";

测试

app.component.html

添加代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div>
<span> test the ng-bootstrap</span>
<div [(ngModel)]="model" ngbRadioGroup name="radioBasic">
<label class="btn btn-primary">
<input type="radio" [value]="1"> Left (pre-checked)
</label>
<label class="btn btn-primary">
<input type="radio" value="middle"> Middle
</label>
<label class="btn btn-primary">
<input type="radio" [value]="false"> Right
</label>
</div>
<hr>
<pre>{{model}}</pre>
</div>

测试结果

angular-ng-bootstrap-result

示例代码

angular + ng-bootstrap

参考文章

NG Bootstrap - Angular directives specific to Bootstrap 4
Bootstrap 4 components, powered by Angular
ngx-translate core

1…121314…24
LieBrother

LieBrother

当才华撑不起野心时,应该静下心来学习;当能力驾驭不了目标时,应该沉下心来历练。

120 日志
38 分类
138 标签
© 2016 - 2019 LieBrother
由 Hexo 强力驱动
主题 - NexT.Mist
本站访客数人次  |  本站总访问量次