在本文中,我们将为您详细介绍PaginationusingAngularJS(withfiltering)的相关知识,此外,我们还会提供一些关于Angular2UserRegistrationandL
在本文中,我们将为您详细介绍Pagination using AngularJS (with filtering)的相关知识,此外,我们还会提供一些关于Angular 2 User Registration and Login Example & Tutorial - Built with Angular 2.0 Final.、angular2 ng2-pagination 分页组件、AngularJs Using $location详解及示例代码、angularjs directive semantic-ui pagination的有用信息。
本文目录一览:- Pagination using AngularJS (with filtering)
- Angular 2 User Registration and Login Example & Tutorial - Built with Angular 2.0 Final.
- angular2 ng2-pagination 分页组件
- AngularJs Using $location详解及示例代码
- angularjs directive semantic-ui pagination
Pagination using AngularJS (with filtering)
Basic: http://www.dispatchertimer.com/angularjs/pagination-using-angularjs/
With filtering: http://www.dispatchertimer.com/angularjs/pagination-with-filtering-using-angularjs/
Angular 2 User Registration and Login Example & Tutorial - Built with Angular 2.0 Final.
http://jasonwatmore.com/post/2016/09/29/angular-2-user-registration-and-login-example-tutorial
Built with Angular 2.0 Final.
After getting a lot of interest in a previous tutorial I posted on how to build a User Registration and Login with Angular 1, and since Angular 2 Final was recently released I thought it was time to post an updated example built with Angular 2 and TypeScript.
The project is available on GitHub at https://github.com/cornflourblue/angular2-registration-login-example.
The example uses a fake backend that stores users in HTML5 local storage, to switch to using a real web service simply remove the fake backend providers in the app.module.ts file below the comment "// providers used to create fake backend".
Here it is in action: (See on Plunker at http://plnkr.co/edit/9luTng?p=preview)
Running the Angular 2 User Registration & Login Example Locally
- Install NodeJS (> v4) and NPM (> v3) from https://nodejs.org/en/download/, you can check the versions you have installed by running
node -v
andnpm -v
from the command line.
- Download the project source code from https://github.com/cornflourblue/angular2-registration-login-example
- Install all required npm packages by running
npm install
from the command line in the project root folder (where the package.json is located).
- Start the application by running
npm start
from the command line in the project root folder.
Angular 2 Project Structure
I used the Angular 2 quickstart project as a base for the application, it''s written in TypeScript and uses systemjs for loading modules. If you''re new to angular 2 I''d recommend checking out the quickstart as it provides details on the project tooling and configuration files which aren''t covered in this post.
The project and code structure mostly follows the recommendations in the official Angular 2 style guide, with my own tweaks here and there.
Each feature has it''s own folder (home & login), other code such as services, models, guards etc are placed in folders prefixed with an underscore to easily differentiate them and group them together at the top of the folder structure.
Here''s the project structure:
- app
- _directives
- alert.component.html
- alert.component.ts
- index.ts
- _guards
- auth.guard.ts
- index.ts
- _helpers
- fake-backend.ts
- index.ts
- _models
- user.ts
- index.ts
- _services
- alert.service.ts
- authentication.service.ts
- index.ts
- user.service.ts
- home
- home.component.html
- home.component.ts
- index.ts
- login
- index.ts
- login.component.html
- login.component.ts
- register
- index.ts
- register.component.html
- register.component.ts
- app.component.html
- app.component.ts
- app.module.ts
- app.routing.ts
- main.ts
- _directives
- app.css
- index.html
- package.json
- system.config.js
- tsconfig.json
- typings.json
Below are brief descriptions and the code for the main files of the example application, all files are available in the github project linked at the top of the post.
Angular 2 Alert Component Template
The alert component template contains the html for displaying alert messages at the top of the page.
1
|
<
div
*
ngIf
=
"message"
[ngClass]="{ ''alert'': message, ''alert-success'': message.type === ''success'', ''alert-danger'': message.type === ''error'' }">{{message.text}}</
div
>
|
Angular 2 Alert Component
The alert component passes alert messages to the template whenever a message is received from the alert service. It does this by subscribing to the alert service''s getMessage() method which returns an Observable.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
import { Component, OnInit } from
''@angular/core''
;
import { AlertService } from
''../_services/index''
;
@Component({
moduleId: module.id,
selector:
''alert''
,
templateUrl:
''alert.component.html''
})
export class AlertComponent {
message: any;
constructor(private alertService: AlertService) { }
ngOnInit() {
this
.alertService.getMessage().subscribe(message => {
this
.message = message; });
}
}
|
Angular 2 Auth Guard
The auth guard is used to prevent unauthenticated users from accessing restricted routes, in this example it''s used in app.routing.ts to protect the home page route. For more information about angular 2 guards you can check out this post on the thoughtram blog.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
import { Injectable } from
''@angular/core''
;
import { Router, CanActivate } from
''@angular/router''
;
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router) { }
canActivate() {
if
(localStorage.getItem(
''currentUser''
)) {
// logged in so return true
return
true
;
}
// not logged in so redirect to login page
this
.router.navigate([
''/login''
]);
return
false
;
}
}
|
Angular 2 Fake Backend Provider
The fake backend provider enables the example to run without a backend / backendless, it uses HTML5 local storage for storing registered user data and provides fake implementations for authentication and CRUD methods, these would be handled by a real api and database in a production application.
It uses the Angular 2 MockBackend to replace the default backend used by the Http service, the MockBackend enables you to intercept http requests made within the application and provide fake responses, it''s also used for unit testing.
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
|
import { Http, BaseRequestOptions, Response, ResponseOptions, RequestMethod } from
''@angular/http''
;
import { MockBackend, MockConnection } from
''@angular/http/testing''
;
export let fakeBackendProvider = {
// use fake backend in place of Http service for backend-less development
provide: Http,
useFactory: (backend, options) => {
// array in local storage for registered users
let users: any[] = JSON.parse(localStorage.getItem(
''users''
)) || [];
// configure fake backend
backend.connections.subscribe((connection: MockConnection) => {
// wrap in timeout to simulate server api call
setTimeout(() => {
// authenticate
if
(connection.request.url.endsWith(
''/api/authenticate''
) && connection.request.method === RequestMethod.Post) {
// get parameters from post request
let params = JSON.parse(connection.request.getBody());
// find if any user matches login credentials
let filteredUsers = users.filter(user => {
return
user.username === params.username && user.password === params.password;
});
if
(filteredUsers.length) {
// if login details are valid return 200 OK with user details and fake jwt token
let user = filteredUsers[0];
connection.mockRespond(
new
Response(
new
ResponseOptions({
status: 200,
body: {
id: user.id,
username: user.username,
firstName: user.firstName,
lastName: user.lastName,
token:
''fake-jwt-token''
}
})));
}
else
{
// else return 400 bad request
connection.mockError(
new
Error(
''Username or password is incorrect''
));
}
}
// get users
if
(connection.request.url.endsWith(
''/api/users''
) && connection.request.method === RequestMethod.Get) {
// check for fake auth token in header and return users if valid, this security is implemented server side in a real application
if
(connection.request.headers.get(
''Authorization''
) ===
''Bearer fake-jwt-token''
) {
connection.mockRespond(
new
Response(
new
ResponseOptions({ status: 200, body: users })));
}
else
{
// return 401 not authorised if token is null or invalid
connection.mockRespond(
new
Response(
new
ResponseOptions({ status: 401 })));
}
}
// get user by id
if
(connection.request.url.match(/\/api\/users\/\d+$/) && connection.request.method === RequestMethod.Get) {
// check for fake auth token in header and return user if valid, this security is implemented server side in a real application
if
(connection.request.headers.get(
''Authorization''
) ===
''Bearer fake-jwt-token''
) {
// find user by id in users array
let urlParts = connection.request.url.split(
''/''
);
let id = parseInt(urlParts[urlParts.length - 1]);
let matchedUsers = users.filter(user => {
return
user.id === id; });
let user = matchedUsers.length ? matchedUsers[0] :
null
;
// respond 200 OK with user
connection.mockRespond(
new
Response(
new
ResponseOptions({ status: 200, body: user })));
}
else
{
// return 401 not authorised if token is null or invalid
connection.mockRespond(
new
Response(
new
ResponseOptions({ status: 401 })));
}
}
// create user
if
(connection.request.url.endsWith(
''/api/users''
) && connection.request.method === RequestMethod.Post) {
// get new user object from post body
let newUser = JSON.parse(connection.request.getBody());
// validation
let duplicateUser = users.filter(user => {
return
user.username === newUser.username; }).length;
if
(duplicateUser) {
return
connection.mockError(
new
Error(
''Username "''
+ newUser.username +
''" is already taken''
));
}
// save new user
newUser.id = users.length + 1;
users.push(newUser);
localStorage.setItem(
''users''
, JSON.stringify(users));
// respond 200 OK
connection.mockRespond(
new
Response(
new
ResponseOptions({ status: 200 })));
}
// delete user
if
(connection.request.url.match(/\/api\/users\/\d+$/) && connection.request.method === RequestMethod.Delete) {
// check for fake auth token in header and return user if valid, this security is implemented server side in a real application
if
(connection.request.headers.get(
''Authorization''
) ===
''Bearer fake-jwt-token''
) {
// find user by id in users array
let urlParts = connection.request.url.split(
''/''
);
let id = parseInt(urlParts[urlParts.length - 1]);
for
(let i = 0; i < users.length; i++) {
let user = users[i];
if
(user.id === id) {
// delete user
users.splice(i, 1);
localStorage.setItem(
''users''
, JSON.stringify(users));
break
;
}
}
// respond 200 OK
connection.mockRespond(
new
Response(
new
ResponseOptions({ status: 200 })));
}
else
{
// return 401 not authorised if token is null or invalid
connection.mockRespond(
new
Response(
new
ResponseOptions({ status: 401 })));
}
}
}, 500);
});
return
new
Http(backend, options);
},
deps: [MockBackend, BaseRequestOptions]
};
|
Angular 2 User Model
The user model is a small class that defines the properties of a user.
1
2
3
4
5
6
|
export class User {
username: string;
password: string;
firstName: string;
lastName: string;
}
|
Angular 2 Alert Service
The alert service enables any component in the application to display alert messages at the top of the page via the alert component.
It has methods for displaying success and error messages, and a getMessage() method that returns an Observable that is used by the alert component to subscribe to notifications for whenever a message should be displayed.
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
|
import { Injectable } from
''@angular/core''
;
import { Router, NavigationStart } from
''@angular/router''
;
import { Observable } from
''rxjs''
;
import { Subject } from
''rxjs/Subject''
;
@Injectable()
export class AlertService {
private subject =
new
Subject<any>();
private keepAfterNavigationChange =
false
;
constructor(private router: Router) {
// clear alert message on route change
router.events.subscribe(event => {
if
(event
instanceof
NavigationStart) {
if
(
this
.keepAfterNavigationChange) {
// only keep for a single location change
this
.keepAfterNavigationChange =
false
;
}
else
{
// clear alert
this
.subject.next();
}
}
});
}
success(message: string, keepAfterNavigationChange =
false
) {
this
.keepAfterNavigationChange = keepAfterNavigationChange;
this
.subject.next({ type:
''success''
, text: message });
}
error(message: string, keepAfterNavigationChange =
false
) {
this
.keepAfterNavigationChange = keepAfterNavigationChange;
this
.subject.next({ type:
''error''
, text: message });
}
getMessage(): Observable<any> {
return
this
.subject.asObservable();
}
}
|
Angular 2 Authentication Service
The authentication service is used to login and logout of the application, to login it posts the users credentials to the api and checks the response for a JWT token, if there is one it means authentication was successful so the user details including the token are added to local storage.
The logged in user details are stored in local storage so the user will stay logged in if they refresh the browser and also between browser sessions until they logout. If you don''t want the user to stay logged in between refreshes or sessions the behaviour could easily be changed by storing user details somewhere less persistent such as session storage or in a property of the authentication service.
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
|
import { Injectable } from
''@angular/core''
;
import { Http, Headers, Response } from
''@angular/http''
;
import { Observable } from
''rxjs/Observable''
;
import
''rxjs/add/operator/map''
@Injectable()
export class AuthenticationService {
constructor(private http: Http) { }
login(username, password) {
return
this
.http.post(
''/api/authenticate''
, JSON.stringify({ username: username, password: password }))
.map((response: Response) => {
// login successful if there''s a jwt token in the response
let user = response.json();
if
(user && user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem(''currentUser
'', JSON.stringify(user));
}
});
}
logout() {
// remove user from local storage to log user out
localStorage.removeItem(''
currentUser'');
}
}
|
Angular 2 User Service
The user service contains a standard set of CRUD methods for managing users, it contains a jwt() method that''s used to add the JWT token from local storage to the Authorization header of each http request.
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
|
import { Injectable } from
''@angular/core''
;
import { Http, Headers, RequestOptions, Response } from
''@angular/http''
;
@Injectable()
export class UserService {
constructor(private http: Http) { }
getAll() {
return
this
.http.get(
''/api/users''
,
this
.jwt()).map((response: Response) => response.json());
}
getById(id) {
return
this
.http.get(
''/api/users/''
+ id,
this
.jwt()).map((response: Response) => response.json());
}
create(user) {
return
this
.http.post(
''/api/users''
, user,
this
.jwt()).map((response: Response) => response.json());
}
update(user) {
return
this
.http.put(
''/api/users/''
+ user.id, user,
this
.jwt()).map((response: Response) => response.json());
}
delete
(id) {
return
this
.http.
delete
(
''/api/users/''
+ id,
this
.jwt()).map((response: Response) => response.json());
}
// private helper methods
private jwt() {
// create authorization header with jwt token
let currentUser = JSON.parse(localStorage.getItem(
''currentUser''
));
if
(currentUser && currentUser.token) {
let headers =
new
Headers({
''Authorization''
:
''Bearer ''
+ currentUser.token });
return
new
RequestOptions({ headers: headers });
}
}
}
|
Angular 2 Home Component Template
The home component template contains html and angular 2 template syntax for displaying a simple welcome message, a list of users and a logout link.
1
2
3
4
5
6
7
8
9
10
11
12
|
<
div
class
=
"col-md-6 col-md-offset-3"
>
<
h1
>Hi {{currentUser.firstName}}!</
h1
>
<
p
>You''re logged in with Angular 2!!</
p
>
<
h3
>All registered users:</
h3
>
<
ul
>
<
li
*
ngFor
=
"let user of users"
>
{{user.username}} ({{user.firstName}} {{user.lastName}})
- <
a
(click)="deleteUser(user.id)">Delete</
a
>
</
li
>
</
ul
>
<
p
><
a
[routerLink]="[''/login'']">Logout</
a
></
p
>
</
div
>
|
Angular 2 Home Component
The home component gets the current user from local storage and all users from the user service, and makes them available to the template.
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
|
import { Component, OnInit } from
''@angular/core''
;
import { User } from
''../_models/index''
;
import { UserService } from
''../_services/index''
;
@Component({
moduleId: module.id,
templateUrl:
''home.component.html''
})
export class HomeComponent implements OnInit {
currentUser: User;
users: User[] = [];
constructor(private userService: UserService) {
this
.currentUser = JSON.parse(localStorage.getItem(
''currentUser''
));
}
ngOnInit() {
this
.loadAllUsers();
}
deleteUser(id) {
this
.userService.
delete
(id).subscribe(() => {
this
.loadAllUsers() });
}
private loadAllUsers() {
this
.userService.getAll().subscribe(users => {
this
.users = users; });
}
}
|
Angular 2 Login Component Template
The login component template contains a login form with username and password fields. It displays validation messages for invalid fields when the submit button is clicked. On submit the login() method is called as long as the form is valid.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<
div
class
=
"col-md-6 col-md-offset-3"
>
<
h2
>Login</
h2
>
<
form
name
=
"form"
(ngSubmit)="f.form.valid && login()" #
f
=
"ngForm"
novalidate>
<
div
class
=
"form-group"
[ngClass]="{ ''has-error'': f.submitted && !username.valid }">
<
label
for
=
"username"
>Username</
label
>
<
input
type
=
"text"
class
=
"form-control"
name
=
"username"
[(ngModel)]="model.username" #
username
=
"ngModel"
required />
<
div
*
ngIf
=
"f.submitted && !username.valid"
class
=
"help-block"
>Username is required</
div
>
</
div
>
<
div
class
=
"form-group"
[ngClass]="{ ''has-error'': f.submitted && !password.valid }">
<
label
for
=
"password"
>Password</
label
>
<
input
type
=
"password"
class
=
"form-control"
name
=
"password"
[(ngModel)]="model.password" #
password
=
"ngModel"
required />
<
div
*
ngIf
=
"f.submitted && !password.valid"
class
=
"help-block"
>Password is required</
div
>
</
div
>
<
div
class
=
"form-group"
>
<
button
[disabled]="loading"
class
=
"btn btn-primary"
>Login</
button
>
<
img
*
ngIf
=
"loading"
src
=
"data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA=="
/>
<
a
[routerLink]="[''/register'']"
class
=
"btn btn-link"
>Register</
a
>
</
div
>
</
form
>
</
div
>
|
Angular 2 Login Component
The login component uses the authentication service to login and logout of the application. It automatically logs the user out when it initializes (ngOnInit) so the login page can also be used to logout.
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
|
import { Component, OnInit } from
''@angular/core''
;
import { Router } from
''@angular/router''
;
import { AlertService, AuthenticationService } from
''../_services/index''
;
@Component({
moduleId: module.id,
templateUrl:
''login.component.html''
})
export class LoginComponent implements OnInit {
model: any = {};
loading =
false
;
constructor(
private router: Router,
private authenticationService: AuthenticationService,
private alertService: AlertService) { }
ngOnInit() {
// reset login status
this
.authenticationService.logout();
}
login() {
this
.loading =
true
;
this
.authenticationService.login(
this
.model.username,
this
.model.password)
.subscribe(
data => {
this
.router.navigate([
''/''
]);
},
error => {
this
.alertService.error(error);
this
.loading =
false
;
});
}
}
|
Angular 2 Register Component Template
The register component template contains a simplae registration form with fields for first name, last name, username and password. It displays validation messages for invalid fields when the submit button is clicked. On submit the register() method is called if the form is valid.
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
|
<
div
class
=
"col-md-6 col-md-offset-3"
>
<
h2
>Register</
h2
>
<
form
name
=
"form"
(ngSubmit)="f.form.valid && register()" #
f
=
"ngForm"
novalidate>
<
div
class
=
"form-group"
[ngClass]="{ ''has-error'': f.submitted && !username.valid }">
<
label
for
=
"firstName"
>First Name</
label
>
<
input
type
=
"text"
class
=
"form-control"
name
=
"firstName"
[(ngModel)]="model.firstName" #
firstName
=
"ngModel"
required />
<
div
*
ngIf
=
"f.submitted && !firstName.valid"
class
=
"help-block"
>First Name is required</
div
>
</
div
>
<
div
class
=
"form-group"
[ngClass]="{ ''has-error'': f.submitted && !username.valid }">
<
label
for
=
"lastName"
>Last Name</
label
>
<
input
type
=
"text"
class
=
"form-control"
name
=
"lastName"
[(ngModel)]="model.lastName" #
lastName
=
"ngModel"
required />
<
div
*
ngIf
=
"f.submitted && !lastName.valid"
class
=
"help-block"
>Last Name is required</
div
>
</
div
>
<
div
class
=
"form-group"
[ngClass]="{ ''has-error'': f.submitted && !username.valid }">
<
label
for
=
"username"
>Username</
label
>
<
input
type
=
"text"
class
=
"form-control"
name
=
"username"
[(ngModel)]="model.username" #
username
=
"ngModel"
required />
<
div
*
ngIf
=
"f.submitted && !username.valid"
class
=
"help-block"
>Username is required</
div
>
</
div
>
<
div
class
=
"form-group"
[ngClass]="{ ''has-error'': f.submitted && !password.valid }">
<
label
for
=
"password"
>Password</
label
>
<
input
type
=
"password"
class
=
"form-control"
name
=
"password"
[(ngModel)]="model.password" #
password
=
"ngModel"
required />
<
div
*
ngIf
=
"f.submitted && !password.valid"
class
=
"help-block"
>Password is required</
div
>
</
div
>
<
div
class
=
"form-group"
>
<
button
[disabled]="loading"
class
=
"btn btn-primary"
>Register</
button
>
<
img
*
ngIf
=
"loading"
src
=
"data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA=="
/>
<
a
[routerLink]="[''/login'']"
class
=
"btn btn-link"
>Cancel</
a
>
</
div
>
</
form
>
</
div
>
|
Angular 2 Register Component
The register component has a single register() method that creates a new user with the user service when the register form is submitted.
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
|
import { Component } from
''@angular/core''
;
import { Router } from
''@angular/router''
;
import { AlertService, UserService } from
''../_services/index''
;
@Component({
moduleId: module.id,
templateUrl:
''register.component.html''
})
export class RegisterComponent {
model: any = {};
loading =
false
;
constructor(
private router: Router,
private userService: UserService,
private alertService: AlertService) { }
register() {
this
.loading =
true
;
this
.userService.create(
this
.model)
.subscribe(
data => {
// set success message and pass true paramater to persist the message after redirecting to the login page
this
.alertService.success(
''Registration successful''
,
true
);
this
.router.navigate([
''/login''
]);
},
error => {
this
.alertService.error(error);
this
.loading =
false
;
});
}
}
|
Angular 2 App Component Template
The app component template is the root component template of the application, it contains a router-outlet directive for displaying the contents of each view based on the current route, and an alert directive for displaying alert messages from anywhere in the system.
1
2
3
4
5
6
7
8
9
|
<!-- main app container -->
<
div
class
=
"jumbotron"
>
<
div
class
=
"container"
>
<
div
class
=
"col-sm-8 col-sm-offset-2"
>
<
alert
></
alert
>
<
router-outlet
></
router-outlet
>
</
div
>
</
div
>
</
div
>
|
Angular 2 App Component
The app component is the root component of the application, it defines the root tag of the app as <app></app> with the selector property.
The moduleId property is set to allow a relative path to be used for the templateUrl.
1
2
3
4
5
6
7
8
9
|
import { Component } from
''@angular/core''
;
@Component({
moduleId: module.id,
selector:
''app''
,
templateUrl:
''app.component.html''
})
export class AppComponent { }
|
Angular 2 App Module
The app module defines the root module of the application along with metadata about the module. For more info about angular 2 modules check out this page on the official docs site.
This is where the fake backend provider is added to the application, to switch to a real backend simply remove the providers located under the comment "// providers used to create fake backend".
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
|
import { NgModule } from
''@angular/core''
;
import { BrowserModule } from
''@angular/platform-browser''
;
import { FormsModule } from
''@angular/forms''
;
import { HttpModule } from
''@angular/http''
;
// used to create fake backend
import { fakeBackendProvider } from
''./_helpers/index''
;
import { MockBackend, MockConnection } from
''@angular/http/testing''
;
import { BaseRequestOptions } from
''@angular/http''
;
import { AppComponent } from
''./app.component''
;
import { routing } from
''./app.routing''
;
import { AlertComponent } from
''./_directives/index''
;
import { AuthGuard } from
''./_guards/index''
;
import { AlertService, AuthenticationService, UserService } from
''./_services/index''
;
import { HomeComponent } from
''./home/index''
;
import { LoginComponent } from
''./login/index''
;
import { RegisterComponent } from
''./register/index''
;
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
routing
],
declarations: [
AppComponent,
AlertComponent,
HomeComponent,
LoginComponent,
RegisterComponent
],
providers: [
AuthGuard,
AlertService,
AuthenticationService,
UserService,
// providers used to create fake backend
fakeBackendProvider,
MockBackend,
BaseRequestOptions
],
bootstrap: [AppComponent]
})
export class AppModule { }
|
Angular 2 App Routing
The app routing file defines the routes of the application, each route contains a path and associated component. The home route is secured by passing the AuthGuard to the canActivate property of the route.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import { Routes, RouterModule } from
''@angular/router''
;
import { HomeComponent } from
''./home/index''
;
import { LoginComponent } from
''./login/index''
;
import { RegisterComponent } from
''./register/index''
;
import { AuthGuard } from
''./_guards/index''
;
const appRoutes: Routes = [
{ path:
''''
, component: HomeComponent, canActivate: [AuthGuard] },
{ path:
''login''
, component: LoginComponent },
{ path:
''register''
, component: RegisterComponent },
// otherwise redirect to home
{ path:
''**''
, redirectTo:
''''
}
];
export const routing = RouterModule.forRoot(appRoutes);
|
Angular 2 Main (Bootstrap) File
The main file is the entry point used by angular to launch and bootstrap the application.
1
2
3
4
5
|
import { platformBrowserDynamic } from
''@angular/platform-browser-dynamic''
;
import { AppModule } from
''./app.module''
;
platformBrowserDynamic().bootstrapModule(AppModule);
|
Angular 2 Development Consultant Sydney
Feel free to drop me a line if you''re looking for an Angular 2 development consultant in Sydney Australia, I also provide remote contracting services for clients outside Sydney.
By Jason Watmore
Tags: Angular 2, Login, Registration, Authentication and Authorization
angular2 ng2-pagination 分页组件
ng2-pagination 分页组件
1、安装插件
npm install ng2-pagination --save
2、如果使用System.js打包那么就需要配置systemjs.config.js文件
A. map中加入以下代码
''ng2-pagination'': ''npm:ng2-pagination''
B. packages中添加以下代码
"ng2-pagination": {
main: ''index.js'',
defaultExtension: ''js''
}
3、app.module.ts主模块中添加此模块,并添加到imports
import {Ng2PaginationModule} from "ng2-pagination"
@NgModule({
imports: [
Ng2PaginationModule
],
4、创建file.component.ts文件,提供数据
import {Component} from "@angular/core";
@Component({
selector: "my-page",
templateUrl: "./app/page.html"
})
export class PageComponent {
info: Array<Object>; //对象数组
constructor() {
this.info = [
{
"id": 1,
"name": "html"
},
{
"id": 2,
"name": "css"
},
{
"id": 3,
"name": "jquey"
},
{
"id": 4,
"name": "angular"
},
{
"id": 5,
"name": "ionic"
},
{
"id": 6,
"name": "angular2"
},
{
"id": 7,
"name": "ionic2"
},
{
"id": 8,
"name": "react"
},
{
"id": 9,
"name": "node"
},
{
"id": 10,
"name": "webpack"
},
{
"id": 11,
"name": "typescript"
}
]
}
}
5、创建模板page.html界面
<ul>
<li *ngFor="let item of info | paginate: { itemsPerPage: 10, currentPage: p }">{{item.name}}</li>
</ul>
<pagination-controls (pageChange)="p = $event"></pagination-controls>
6、提高篇,分页的数据一般都是有父组件提供的,所以数据应该由属性传递给@Input然后获取他的值。 部分代码
父组件 .ts文件 提供数据
export class FatherComponent {
result: Array<Object>;
constructor() {
this.result = [
{
"id": 1,
"name": "html"
},
{
"id": 2,
"name": "css"
},
{
"id": 3,
"name: "js"
}
]
}
}
父组件 .html文件
<!-- 把父组件的信息传递给分页组件, 进行分页。 -->
<my-page [info]="result"></my-page>
分页组件 .ts文件 使用Input模块获取属性传递过来的数据 info
import {Component, Input} from "@angular/core";
@Component({
selector: "my-page",
templateUrl: "./app/page.html"
})
export class PageComponent {
// 使用@Input接受传递过来的变量,操作。
@Input()
info: Array<Object>;
}
分页模板代码不变,通过info获取数据
<ul>
<li *ngFor="let item of info | paginate: { itemsPerPage: 10, currentPage: p }">{{item.name}}</li>
</ul>
<pagination-controls (pageChange)="p = $event"></pagination-controls>
7、最后修改分页英文字母为中文的文件
node_modules/ng2-pagination/dist/template.js 修改上一页、下一页
8、注意
其实,这个分页组件重在循环html部分内容,ts文件只是提供数据,所以,最好的用法就是,每个需要分页的组件的模板中,加入分页组件的这段html代码就可以了,不需要专门命名为page组件然后公用,这样有局限性,不同的分页内容不同,所以循环出来的字段名称肯定不同。所以最好不要由父组件提供数据,调用分页模板,这样有很大的局限性。
AngularJs Using $location详解及示例代码
一、What does it do?
$location服务分析浏览器地址栏中的URL(基于window.location),让我们可以在应用中较为方便地使用URL里面的东东。在地址栏中更改URL,会响应到$location服务中,而在$location中修改URL,也会响应到地址栏中。
$location服务:
暴露当前浏览器地址栏的URL,所以我们可以
1.注意和观察URL
2.改变URL
当用户做以下操作时,与浏览器一起同步URL:
1.改变地址栏
2.单击后退或者前进按钮(或者点击一个历史链接)。
3.单击一个链接
将URL对象描绘为一系列的方法(protocol,host,path,search,hash)。
1. 比较$location和window.location
1) 目的:window.location和$location服务,都允许对当前浏览器的location进行读写访问。
2) API:window.location暴露一个未经加工的对象,附带一些可以直接修改的属性;而$location服务则是暴露一些jQuery风格的getter/setter方法。
3) 与angular应用声明周期的整合:$location知道关于所有内部声明周期的阶段,与$watch等整合;而window.location则不行。
4) 与HTML5 API无缝结合:是(with a fallback for legacy browsers,对于低版本的浏览器有兼容手段?);而window.location则没有。
5) 知道应用加载的文档根目录(docroot)或者上下文(context):window.location不行,wnidow.location.path会返回”/docroot/子路径”;而$location.path()返回真实的docroot。
2. When should I use $location?
在应用中,任何需要对当前URL的改变作出响应,或者想去改变当前浏览器的URL的时候。
3. What does it not do?
当浏览器URL改变的时候,不会导致页面重新加载(page reload)。如果需要做这件事情(更改地址,实现page reload),请使用较低级别的API,$window.location.href。
二、General overview of the API(API的总体概述)
$location 服务可以根据它初始化时的配置而有不同的表现。默认配置是适合大多数应用的,其他配置定制,可以开启一些新特性。
当$location服务初始化完毕,我们可以以jQuery风格的getter、setter方法来使用它,允许我们获得或者改变当前浏览器的URl。
1. $location service configuration
想配置$location服务,需要获得$locationProvider(http://code.angularjs.org/1.0.2/docs/api/ng.$locationProvider),并设置以下参数:
html5Mode(mode):{boolean},true - see HTML5 mode;false - see Hashbang mode,默认: false。(下面的章节会解释各种mode)
hashPrefix(prefix):{string},hashbang使用的前缀(html5Mode为false时,使用hashbang mode,以适应不支持HTML5 mode的浏览器),默认:''!''
2. Getter and setter methods
$location 服务为只读的URL部分(absUrl,protocol,host,port)提供getter方法,也提供url,path,search,hash的getter、setter方法。
// get the current path $location.path(); // change the path $location.path(''/newValue'')
所有setter方法都返回同一个$location对象,以实现链式语法。例如,在一句里面修改多个属性,链式setter方法类似:
$location.path(‘/newValue'').search({key:value});
有一个特别的replace方法,可以用作告诉$location服务,在下一次与浏览器同步时,使用某个路径代替最新的历史记录,而不是创建一个新的历史记录。当我们想实现重定向(redirection)而又不想使后退按钮(后退按钮回重新触发重定向)失效时,replace方法就很有用了。想改变当前URL而不创建新的历史记录的话,我们可以这样做:
$location.path(‘/someNewPath'').replace();
注意,setter方法不会马上更新window.location。相反,$location服务会知道scope生命周期以及合并多个$location变化为一个,并在scope的$digest阶段一并提交到window.location对象中。正因为$location多个状态的变化会合并为一个变化,到浏览器中,只调用一次replace()方法,让整个commit只有一个replace(),这样不会使浏览器创建额外的历史记录。一旦浏览器更新了,$location服务会通过replace()方法重置标志位,将来的变化将会创建一个新的历史记录,除非replace()被再次调用。
Setter and character encoding
我们可以传入特殊字符到$location服务中,服务会按照RFC3986标准,自动对它们进行编码。当我们访问这些方法时:
- 所有传入$location的setter方法的值,path()、search()、hash(),都会被编码。
- getter方法(没参数)返回的值都是经过解码的,如path(),search(),hash()。
- 当我们调用absUrl()方法时,返回的值是包含已编码部分的完整url。
- 当我们调用url()方法时,返回的是包含path、search和hash部分的已经编码的url,如/path?search=1&b=c#hash。
三、Hashbang and HTML5 Modes
$location服务有两个配置模式,可以控制浏览器地址栏的URL格式:Hashbang mode(默认)与基于使用HTML5 History API的HTML5 mode。在两种模式下,应用都使用相同的API,$location服务会与正确的URL片段、浏览器API一起协作,帮助我们进行浏览器URL变更以及历史管理。
1. Hashbang mode (default mode)
在这个模式中,$location在所有浏览器中都使用Hashbang URL。查看下面的代码片段,可以了解更多:
it(''should show example'', inject( function($locationProvider) { $locationProvider.html5mode = false; $locationProvider.hashPrefix = ''!''; }, function($location) { // open http://host.com/base/index.html#!/a $location.absUrl() == ''http://host.com/base/index.html#!/a''; $location.path() == ''/a''; $location.path(''/foo''); $location.absUrl() == ''http://host.com/base/index.html#!/foo''; $location.search() == {};//search没东东的时候,返回空对象 $location.search({a: ''b'', c: true}); $location.absUrl() == ''http://host.com/base/index.html#!/foo?a=b&c''; $location.path(''/new'').search(''x=y'');//可以用字符串的方式更改search,每次设置search,都会覆盖之前的search $location.absUrl() == ''http://host.com/base/index.html#!/new?x=y''; } ));
Crawling your app(让google能够对我们的应用进行索引)
如果我们想让我们的Ajax应用能够被索引,我们需要在head中增加一个特殊的meta标签:
<meta name="fragment" content="!" />
这样做,将让爬虫机器人使用_escaped_fragment_参数请求当前的链接,让我们的服务器认识爬虫机器人,并提供对应的HTML快照。想了解更多关于这个技术的信息,可以查看https://developers.google.com/webmasters/ajax-crawling/docs/specification?hl=zh-CN
四、HTML5 mode
在HTML5模式中,$location服务的getter、setter通过HTML5的History API与浏览器URL进行交互,允许使用正规的path、search模块,代替hashbang的模式。如果部分浏览器不支持HTML5 History API,$location服务会自动退回到使用hashbang URL的模式。为了让我们能够从不清楚显示我们的应用的浏览器是否支持history API的担心中解脱出来,使用$location服务是一个正确的、最佳的选择。
在旧版浏览器中打开一个正规的URL会转换为hashbangURL。
在现代浏览器中打开一个hashbangURL,会重写为一个正规的URL。
1. 向前兼容旧版浏览器
对于支持HTML5 history API的浏览器,$location回使用它们去写path和search。如果浏览器不支持history API,$location会转为提供Hashbang URL。这是$location服务自动转换的。
2. HTML link rewriting
当我们使用history API mode的时候,我们对于不同的浏览器,需要不同的链接,但我们只需要提供正规的URL即可,例如<a href=”/some?foo=bar”>link</a>
当用户单击这个超链接时:
在旧的浏览器中,URL会改为/index.html#!/some?foo=bar
在现代浏览器中,URL会改为/some?foo=bar
在下面的情况中,链接不会被重写,而是会使页面加载到对应Url中:
包含target的超链接:<a href="/ext/link?a=b" target="_self">link</a>
到不同domain的绝对链接:<a href="http://angularjs.org/">link</a>
设置了base路径后,通过” /”开头的链接到不同base路径的超链接:<a href="/not-my-base/link">link</a>
3. server side
使用这个方式,在服务端请求URL重定向,通常,我们需要重定向我们所有的链接到我们的应用中。(例如index.html)。
4. Crawling your app
与之前相同
5. Relative links
确保检查所有相对链接、图片、脚本等。我们必须在<head>中指定base url(<base href="/my-base">),并在所有地方使用绝对url(以/开头)。因为相对URL会根据document的初始路径(通常与应用的root有所不同),转化为绝对url。(relative urls will be resolved to absolute urls using the initial absolute url of the document, which is often different from the root of the application)。
我们十分鼓励在document root中运行允许使用History API的angular应用,因为这很好地照顾到相对链接的问题。
6. Sending links among different browsers
(这里讲解了两种模式的地址可以适应不同浏览器,自动转换,又重复讲一次……)
7. 例子
在这例子中,可以看到两个$location实例,两个都是html5 mode,但在不同的浏览器上,所以我们可以看到两者之间的不同点。这些$location服务与两个假的“浏览器”连接。每一个input代表浏览器的地址栏。
注意,当我们输入hashbang地址到第一个“浏览器”(或者第二个?),它不会重写或重定向另外的Url,这个转换过程只会发生在page reload的时候。
<!DOCTYPE html> <html ng-app> <head> <base href=""/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>fake-browser</title> <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"> <style type="text/css"> .ng-cloak { display: none; } </style> </head> <body> <div ng-non-bindable> <div id="html5-mode" ng-controller="Html5Cntl"> <h4>Browser with History API</h4> <div ng-address-bar browser="html5"></div><br><br> $location.protocol() = {{$location.protocol()}}<br> $location.host() = {{$location.host()}}<br> $location.port() = {{$location.port()}}<br> $location.path() = {{$location.path()}}<br> $location.search() = {{$location.search()}}<br> $location.hash() = {{$location.hash()}}<br> <a href="http://www.host.com/base/first?a=b">/base/first?a=b</a> | <a href="http://www.host.com/base/sec/ond?flag#hash">sec/ond?flag#hash</a> | <a href="/other-base/another?search">external</a> </div> <div id="hashbang-mode" ng-controller="HashbangCntl"> <h4>Browser without History API</h4> <div ng-address-bar browser="hashbang"></div><br><br> $location.protocol() = {{$location.protocol()}}<br> $location.host() = {{$location.host()}}<br> $location.port() = {{$location.port()}}<br> $location.path() = {{$location.path()}}<br> $location.search() = {{$location.search()}}<br> $location.hash() = {{$location.hash()}}<br> <a href="http://www.host.com/base/first?a=b">/base/first?a=b</a> | <a href="http://www.host.com/base/sec/ond?flag#hash">sec/ond?flag#hash</a> | <a href="/other-base/another?search">external</a> </div> </div> <script src="../angular.js" type="text/javascript"></script> <script type="text/javascript"> function FakeBrowser(initUrl, baseHref) { this.onUrlChange = function(fn) { this.urlChange = fn; }; this.url = function() { return initUrl; }; this.defer = function(fn, delay) { setTimeout(function() { fn(); }, delay || 0); }; this.baseHref = function() { return baseHref; }; this.notifyWhenOutstandingRequests = angular.noop; } var browsers = { html5: new FakeBrowser(''http://www.host.com/base/path?a=b#h'', ''/base/index.html''), hashbang: new FakeBrowser(''http://www.host.com/base/index.html#!/path?a=b#h'', ''/base/index.html'') }; function Html5Cntl($scope, $location) { $scope.$location = $location; } function HashbangCntl($scope, $location) { $scope.$location = $location; } function initEnv(name) { var root = angular.element(document.getElementById(name + ''-mode'')); angular.bootstrap(root, [ function ($compileProvider, $locationProvider, $provide) { debugger; $locationProvider.html5Mode(true).hashPrefix(''!''); $provide.value(''$browser'', browsers[name]); $provide.value(''$document'', root); $provide.value(''$sniffer'', {history:name == ''html5''}); $compileProvider.directive(''ngAddressBar'', function () { return function (scope, elm, attrs) { var browser = browsers[attrs.browser], input = angular.element(''<input type="text">'').val(browser.url()), delay; input.bind(''keypress keyup keydown'', function () { if (!delay) { delay = setTimeout(fireUrlChange, 250); } }); browser.url = function (url) { return input.val(url); }; elm.append(''Address: '').append(input); function fireUrlChange() { delay = null; browser.urlChange(input.val()); } }; }); } ]); root.bind(''click'', function (e) { e.stopPropagation(); }); } initEnv(''html5''); initEnv(''hashbang''); </script> </body> </html>
五、附加说明
1. Page reload navigation
$location服务仅仅允许我们改变URl;它不允许我们重新加载页面(reload the page)。当我们需要改变URL且reload page或者跳转到其他页面时,我们需要使用低级点得API,$window.location.href。
2. Using $location outside of the scope life-cycle
$location知道angular的scope life-cycle。当浏览器的URL发生改变时,它会更新$location,并且调用$apply,所以所有$watcher和$observer都会得到通知。当我们再$digest阶段中修改$location,不会出现任何问题;$location会将这次修改传播到浏览器中,并且通知所有$watcher、$observer。当我们需要在angular外面改变$location时(例如在DOM事件中或者在测试中),我们必须调用$apply,以传播这个变化。
3. $location.path() and ! or / prefixes
path可以直接使用”/”开始;$location.path()setter会在value没有以”/”开头时自动补上。
注意”!”前缀,在Hashbang mode中,不属于$location.path()的一部分。它仅仅是hashPrefix。
六、Testing with the $location service
在测试中使用$location服务的时候,是处于angular scope life-cycle外面的。这意味着我们需要负责调用scope.apply()。
describe(''serviceUnderTest'', function() { beforeEach(module(function($provide) { $provide.factory(''serviceUnderTest'', function($location){ // whatever it does... }); }); it(''should...'', inject(function($location, $rootScope, serviceUnderTest) { $location.path(''/new/path''); $rootScope.$apply(); // test whatever the service should do... })); });
七、Migrating from earlier AngularJS releases
在早期的angular中,$location使用hashPath或者hashSearch去处理path和search方法。在这个release中,当有需要的时候,$location服务处理path和search方法,然后使用那些获得得信息去构成hashbang URL(例如http://server.com/#!/path?search=a)。
八、Two-way binding to $location
angular compiler当前不支持方法的双向绑定(https://github.com/angular/angular.js/issues/404)。如果我们希望对$location对象实现双向绑定(在input中使用ngModel directive),我们需要指定一个额外的model属性(例如:locationPath),并加入两个$watch,监听两个方向上的$location更新,例如:
<input type="text" ng-model="locationPath" />
// js - controller $scope.$watch(''locationPath'', function(path) { $location.path(path); ); $scope.$watch(''$location.path()'', function(path) { scope.locationPath = path; });
以上就是关于AngularJs Using $location的资料整理,后续继续补充相关资料,谢谢大家对本站的支持!
- AngularJS通过$location获取及改变当前页面的URL
- AngularJS内建服务$location及其功能详解
- AngularJS的$location使用方法详解
angularjs directive semantic-ui pagination
ui.semantic.pagination.js
(function (angular) {
angular.module(''ui.semantic.pagination'', [])
.controller(''PaginationController'', [''$scope'', ''$attrs'', ''$parse'', function ($scope, $attrs, $parse) {
var self = this,
ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl
setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop;
this.init = function (ngModelCtrl_, config) {
ngModelCtrl = ngModelCtrl_;
this.config = config;
ngModelCtrl.$render = function () {
self.render();
};
if ($attrs.itemsPerPage) {
$scope.$parent.$watch($parse($attrs.itemsPerPage), function (value) {
self.itemsPerPage = parseInt(value, 10);
$scope.totalPages = self.calculateTotalPages();
});
} else {
this.itemsPerPage = config.itemsPerPage;
}
};
this.calculateTotalPages = function () {
var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage);
return Math.max(totalPages || 0, 1);
};
this.render = function () {
$scope.page = parseInt(ngModelCtrl.$viewValue, 10) || 1;
};
$scope.selectPage = function (page) {
if ($scope.page !== page && page > 0 && page <= $scope.totalPages) {
ngModelCtrl.$setViewValue(page);
ngModelCtrl.$render();
}
};
$scope.getText = function (key) {
return $scope[key + ''Text''] || self.config[key + ''Text''];
};
$scope.noPrevious = function () {
return $scope.page === 1;
};
$scope.noNext = function () {
return $scope.page === $scope.totalPages;
};
$scope.$watch(''totalItems'', function () {
$scope.totalPages = self.calculateTotalPages();
});
$scope.$watch(''totalPages'', function (value) {
setNumPages($scope.$parent, value); // Readonly variable
if ($scope.page > value) {
$scope.selectPage(value);
} else {
ngModelCtrl.$render();
}
});
}])
.constant(''paginationConfig'', {
itemsPerPage: 10,
boundaryLinks: false,
directionLinks: true,
firstText: ''First'',
previousText: ''Previous'',
nextText: ''Next'',
lastText: ''Last'',
numDisplayEntries: 6, //连续分页主体部分分页条目数
numEdgeEntries: 2, //两侧首尾分页条目数
rotate: true
})
.directive(''pagination'', [''$parse'', ''paginationConfig'', function ($parse, paginationConfig) {
return {
restrict: ''EA'',
scope: {
totalItems: ''='',
firstText: ''@'',
previousText: ''@'',
nextText: ''@'',
lastText: ''@''
},
require: [''pagination'', ''?ngModel''],
controller: ''PaginationController'',
templateUrl: ''/UserControls/pagination.html'',
replace: true,
link: function (scope, element, attrs, ctrls) {
var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];
if (!ngModelCtrl) {
return; // do nothing if no ng-model
}
// Setup configuration parameters
var maxSize = angular.isDefined(attrs.maxSize) ? scope.$parent.$eval(attrs.maxSize) : paginationConfig.maxSize,
rotate = angular.isDefined(attrs.rotate) ? scope.$parent.$eval(attrs.rotate) : paginationConfig.rotate;
scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks;
scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : paginationConfig.directionLinks;
var num_display_entries = angular.isDefined(attrs.numDisplayEntries) ? scope.$parent.$eval(attrs.numDisplayEntries) : paginationConfig.numDisplayEntries,
num_edge_entries = angular.isDefined(attrs.numEdgeEntries) ? scope.$parent.$eval(attrs.numEdgeEntries) : paginationConfig.numEdgeEntries;
paginationCtrl.init(ngModelCtrl, paginationConfig);
if (attrs.maxSize) {
scope.$parent.$watch($parse(attrs.maxSize), function (value) {
maxSize = parseInt(value, 10);
paginationCtrl.render();
});
}
// Create page object used in template
function makePage(number, text, isActive) {
return {
number: number,
text: text,
active: isActive,
disabled: text == ''...'',
};
}
function getPages2(currentPage, totalPages) {
var ret = [];
var num_edge_entries = 2;
var np = totalPages;
var interval = getInterval(currentPage - 1, totalPages);
// Generate starting points
if (interval[0] > 0 && num_edge_entries > 0) {
var end = Math.min(num_edge_entries, interval[0]);
for (var i = 0; i < end; i++) {
var page = makePage(i + 1, i + 1, (i + 1) === currentPage);
ret.push(page);
}
if (num_edge_entries < interval[0]) {
var page = makePage(-1, ''...'', false);
ret.push(page);
}
}
// Generate interval links
for (var i = interval[0]; i < interval[1]; i++) {
var page = makePage(i + 1, i + 1, (i + 1) === currentPage);
ret.push(page);
}
// Generate ending points
if (interval[1] < np && num_edge_entries > 0) {
if (np - num_edge_entries > interval[1]) {
var page = makePage(-1, ''...'', false);
ret.push(page);
}
var begin = Math.max(np - num_edge_entries, interval[1]);
for (var i = begin; i < np; i++) {
var page = makePage(i + 1, i + 1, (i + 1) === currentPage);
ret.push(page);
}
}
return ret;
}
function getPages(currentPage, totalPages) {
var pages = [];
// Default page limits
var startPage = 1, endPage = totalPages;
var isMaxSized = (angular.isDefined(maxSize) && maxSize < totalPages);
// recompute if maxSize
if (isMaxSized) {
if (rotate) {
// Current page is displayed in the middle of the visible ones
startPage = Math.max(currentPage - Math.floor(maxSize / 2), 1);
endPage = startPage + maxSize - 1;
// Adjust if limit is exceeded
if (endPage > totalPages) {
endPage = totalPages;
startPage = endPage - maxSize + 1;
}
} else {
// Visible pages are paginated with maxSize
startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1;
// Adjust last page if limit is exceeded
endPage = Math.min(startPage + maxSize - 1, totalPages);
}
}
// Add page number links
for (var number = startPage; number <= endPage; number++) {
var page = makePage(number, number, number === currentPage);
pages.push(page);
}
// Add links to move between page sets
if (isMaxSized && !rotate) {
if (startPage > 1) {
var previousPageSet = makePage(startPage - 1, ''...'', false);
pages.unshift(previousPageSet);
}
if (endPage < totalPages) {
var nextPageSet = makePage(endPage + 1, ''...'', false);
pages.push(nextPageSet);
}
}
return pages;
}
/**
* Calculate start and end point of pagination links depending on
* currentPage and num_display_entries.
* @return {Array}
*/
function getInterval(currentPage, pageCount) {
//var num_display_entries = 6;
//var num_edge_entries = 2;
var ne_half = Math.ceil(num_display_entries / 2);
var np = pageCount;
var upper_limit = np - num_display_entries;
var start = currentPage > ne_half ? Math.max(Math.min(currentPage - ne_half, upper_limit), 0) : 0;
var end = currentPage > ne_half ? Math.min(currentPage + ne_half, np) : Math.min(num_display_entries, np);
return [start, end];
}
var originalRender = paginationCtrl.render;
paginationCtrl.render = function () {
originalRender();
if (scope.page > 0 && scope.page <= scope.totalPages) {
scope.pages = getPages2(scope.page, scope.totalPages);
}
};
}
};
}]);
})(angular);
pagination.html
<div>
<ang-data-ng-click="selectPage(page - 1)">
<i></i>
</a>
<adata-ng-repeat="page in pages track by $index"
data-ng-data-ng-click="selectPage(page.number)">
{{page.text}}
</a>
<ang-data-ng-click="selectPage(page + 1)">
<i></i>
</a>
</div>
今天关于Pagination using AngularJS (with filtering)的讲解已经结束,谢谢您的阅读,如果想了解更多关于Angular 2 User Registration and Login Example & Tutorial - Built with Angular 2.0 Final.、angular2 ng2-pagination 分页组件、AngularJs Using $location详解及示例代码、angularjs directive semantic-ui pagination的相关知识,请在本站搜索。
本文标签: