angular6入门实战,环境搭建、添加组件、服务、路由和HTTP

目录

一、新建web项目

二、启动项目

三、添加表格,css控制隔行变色

四、创建组件

五、显示列表

创建模拟数据

导入

用* ngFor 列出

使用* ngIf 隐藏空白详细信息

设置所选样式

添加单击事件绑定

添加单击事件处理程序

六、主/明细组件

建立HeroDetailComponent

添加属性@Input()

七、服务

创建HeroService 

获取数据

更新HeroesComponent

注入HeroService

添加getHeroes()

调用ngOnInit

可观察的数据

创建MessagesComponent 

创建MessageService 

八、路由

添加AppRoutingModule

添加路线

RouterModule.forRoot()

添加RouterOutlet 

添加仪表板视图

添加仪表板路由

添加默认路由

九、http

启用HTTP服务

更新

添加和删除

按名称搜索

创建HeroSearchComponent

十、集成bootstrap和jasper报表

安装bootstrap

导入bootstrap样式

创建报表组件


在开始之前,请确保您的计算机上有Node.js.

查看版本:ng version

一、新建web项目

输入项目名称

等待编译完成

编译完成

等同命令:ng new mosesAgl 然后用idea打开项目

二、启动项目

浏览界面

三、添加表格,css控制隔行变色

 

在app.component.html文件中添加表格

<table width='600' border='0' cellspacing='0' cellpadding='0' align='center'>

    <tr>

      <td>TSNAME</td>

      <td>ALLSIZE</td>

      <td>USEDSIZE</td>

      <td>FREESIZE</td>

      <td>SYL%</td>

    </tr>

    <tr>

      <td>USERS</td>

      <td>32767.98</td>

      <td>4</td>

      <td>32763.98</td>

      <td>.01</td>

    </tr>

    <tr>

      <td>UNDOTBS1</td>

      <td>32767.98</td>

      <td>13.56</td>

      <td>32754.42</td>

      <td>.04</td>

    </tr>

    <tr>

      <td>REGISTRATION</td>

      <td>120</td>

      <td>.06</td>

      <td>119.94</td>

      <td>.05</td>

    </tr>

    <tr>

      <td>TANG</td>

      <td>70</td>

      <td>.13</td>

      <td>69.88</td>

      <td>.18</td>

    </tr>

    <tr>

      <td>EXAMPLE</td>

      <td>32767.98</td>

      <td>68.25</td>

      <td>32699.73</td>

      <td>.21</td>

    </tr>

    <tr>

      <td>TBS</td>

      <td>32767.98</td>

      <td>.56</td>

      <td>32767.42</td>

      <td>0</td>

    </tr>

  </table>

在app.component.css文件中添加样式

body {

  font-family: Arial;

  font-size: 14px;

  line-height: 180%;

  padding-top: 20px;

}

 

/*第一行标题蓝色背景*/

table tr:first-child {

  background: #0066CC;

  color: #fff;

  font-weight: bold;

}

 

table {

  border-top: 1pt solid #C1DAD7;

  border-left: 1pt solid #C1DAD7;

  margin: 0 auto;

}

 

td {

  padding: 5px 10px;

  text-align: center;

  border-right: 1pt solid #C1DAD7;

  border-bottom: 1pt solid #C1DAD7;

}

 

/* odd 标识奇数行,even标识偶数行 */

tr:nth-of-type(odd) {

  background: #c6f9f7

}

 

/*3的倍数行红色背景*/

tr:nth-child(3n+1) {

  background: #FF0000;

}

 

/* 悬停鼠标变色 */

tr:hover {

  background: #E0F0F0;

}

界面效果

四、创建组件

ng generate component heroes

添加一个hero属性HeroesComponent

heroes.component.ts

hero = 'Windstorm';

heroes.component.html

{{hero}}

显示HeroesComponent视图

app.component.html
<h1>{{title}}</h1>
<app-heroes></app-heroes>

创建一个Hero类

Hero在文件src/app夹中的自己的文件中创建一个类。给它idname属性。

hero.ts

export class Hero {
  id: number;
  name: string;
}

将组件的hero属性重构为类型Hero。与初始化它id1而得名Windstorm

heroes.component.ts

import {Component, OnInit} from '@angular/core';
import {Hero} from '../hero';

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
  hero: Hero = {
    id: 1,
    name: 'Windstorm'
  };

  constructor() {
  }

  ngOnInit() {
  }

}

更新模板中的绑定,名字idname在详细信息布局中显示

heroes.component.html

<!--格式化-->
<h2>{{hero.name | uppercase}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div><span>name: </span>{{hero.name}}</div>
<!--双向绑定 需要导入FormsModule-->
<div>
  <label>name:
    <input [(ngModel)]="hero.name" placeholder="name">
  </label>
</div>

导入FormsModule 

app.module.ts

import {FormsModule} from '@angular/forms'; // <-- NgModel lives here

imports: [
  BrowserModule,
  FormsModule
],

请注意,AppModule 声明两个应用程序组件,AppComponentHeroesComponent

五、显示列表

创建模拟数据

mock-heroes.ts

import { Hero } from './hero';

export const HEROES: Hero[] = [
  { id: 11, name: 'Mr. Nice' },
  { id: 12, name: 'Narco' },
  { id: 13, name: 'Bombasto' },
  { id: 14, name: 'Celeritas' },
  { id: 15, name: 'Magneta' },
  { id: 16, name: 'RubberMan' },
  { id: 17, name: 'Dynama' },
  { id: 18, name: 'Dr IQ' },
  { id: 19, name: 'Magma' },
  { id: 20, name: 'Tornado' }
];

导入

heroes.component.ts

import { HEROES } from '../mock-heroes';

heroes = HEROES;

* ngFor 列出

heroes.component.html

<li *ngFor="let hero of heroes">

使用* ngIf 隐藏空白详细信息

<div *ngIf="selectedHero">

设置所选样式

添加[class.selected]绑定到<li>HeroesComponent模板

添加单击事件绑定

<li *ngFor="let hero of heroes" (click)="onSelect(hero)">

heroes.component.html完整代码

<h2>My Heroes</h2>
<ul class="heroes">
  <!--添加[class.selected]绑定到<li>的HeroesComponent模板-->
  <!--添加单击事件绑定-->
  <li *ngFor="let hero of heroes"
      [class.selected]="hero === selectedHero"
      (click)="onSelect(hero)">
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </li>
</ul>
<!--使用* ngIf 隐藏空白详细信息-->
<div *ngIf="selectedHero">
  <!--格式化-->
  <h2>{{selectedHero.name | uppercase}} Details</h2>
  <div><span>id: </span>{{selectedHero.id}}</div>
  <div>
    <label>name:
      <!--双向绑定 需要导入FormsModule-->
      <input [(ngModel)]="selectedHero.name" placeholder="name">
    </label>
  </div>

</div>

添加单击事件处理程序

heroes.component.ts

selectedHero: Hero;

onSelect(hero: Hero): void {
  this.selectedHero = hero;
}

六、主/明细组件

建立HeroDetailComponent

ng generate component hero-detail

HeroesComponent模板底部剪切详细信息的HTML ,并将其粘贴到模板中生成的样板上HeroDetailComponent

<!--使用* ngIf 隐藏空白详细信息-->
<div *ngIf="selectedHero">
  <!--格式化-->
  <h2>{{selectedHero.name | uppercase}} Details</h2>
  <div><span>id: </span>{{selectedHero.id}}</div>
  <div>
    <label>name:
      <!--双向绑定 需要导入FormsModule-->
      <input [(ngModel)]="selectedHero.name" placeholder="name">
    </label>
  </div>

</div>

添加属性@Input()

HeroDetailComponent类文件导入Hero符号

hero-detail.component.ts

import { Hero } from '../hero';

修改@angular/core import语句以包含该Input符号

import { Component, OnInit, Input } from '@angular/core';

添加一个hero属性,前面是装饰器。@Input()

@Input() hero: Hero;

外部绑定它

heroes.component.html

<app-hero-detail [hero]="selectedHero"></app-hero-detail>

七、服务

创建HeroService 

ng generate service hero

获取数据

hero.service.ts

导入HeroHEROES

import { Hero } from './hero';
import { HEROES } from './mock-heroes';

添加一个getHeroes方法。

getHeroes(): Hero[] {
  return HEROES;
}

更新HeroesComponent

删除HEROES导入,导入HeroService

import { HeroService } from '../hero.service';

heroes简单的声明替换属性的定义

heroes: Hero[];

注入HeroService

constructor(private heroService: HeroService) { }

添加getHeroes()

getHeroes(): void { this.heroes = this.heroService.getHeroes(); }

调用ngOnInit

ngOnInit() { this.getHeroes(); }

可观察的数据

hero.service.ts

打开HeroService文件并从RxJS 导入Observableof符号

import { Observable, of } from 'rxjs';

替换getHeroes方法

getHeroes(): Observable<Hero[]> { return of(HEROES); }

heroes.component.ts

getHeroes(): void { this.heroService.getHeroes() .subscribe(heroes => this.heroes = heroes); }

创建MessagesComponent 

ng generate component messages

修改AppComponent模板以显示生成的MessagesComponent

app.component.html

<app-messages></app-messages>

创建MessageService 

ng generate service message

替换message.service.ts内容

import {Injectable} from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class MessageService {
  messages: string[] = [];

  add(message: string) {
    this.messages.push(message);
  }

  clear() {
    this.messages = [];
  }
}

HeroService导入MessageService

import { MessageService } from './message.service';

constructor(private messageService: MessageService) { }

修改getHeroes方法以在获取英雄时发送消息

getHeroes(): Observable<Hero[]> {
  // TODO: send the message _after_ fetching the heroes
  this.messageService.add('HeroService: fetched heroes');
  return of(HEROES);
}

MessagesComponent导入MessageService

import { MessageService } from '../message.service';

constructor(public messageService: MessageService) {}

使用MessagesComponent以下内容替换CLI生成的模板

<div *ngIf="messageService.messages.length">
  <h2>Messages</h2>
  <button class="clear"
          (click)="messageService.clear()">clear
  </button>
  <div *ngFor='let message of messageService.messages'> {{message}}</div>
</div>

八、路由

添加AppRoutingModule

ng generate module app-routing --flat --module=app

--flat放入文件src/app而不是自己的文件夹。
--module=app告诉CLI将其注册到imports数组中AppModule

添加路线

import { HeroesComponent }      from './heroes/heroes.component';

const routes: Routes = [
  { path: 'heroes', component: HeroesComponent }
];

 

  1. path:与浏览器地址栏中的URL匹配的字符串。
  2. component:导航到此路由时路由器应创建的组件。

RouterModule.forRoot()

imports: [ RouterModule.forRoot(routes) ],

 

添加RouterOutlet 

AppComponent模板用<router-outlet>元素替换<app-heroes>元素。

<router-outlet></router-outlet>

<nav> <a routerLink="/heroes">Heroes</a> </nav>

app.component.html

<h1>{{title}}</h1>
<nav>
  <a routerLink="/dashboard">Dashboard</a>
  <a routerLink="/heroes">Heroes</a>
</nav>
<router-outlet></router-outlet>
<app-messages></app-messages>

css控制隔行变色table及其样式移动到了hero-detail

app.component.css
h1 {
  font-size: 1.2em;
  color: #999;
  margin-bottom: 0;
}

h2 {
  font-size: 2em;
  margin-top: 0;
  padding-top: 0;
}

nav a {
  padding: 5px 10px;
  text-decoration: none;
  margin-top: 10px;
  display: inline-block;
  background-color: #eee;
  border-radius: 4px;
}

nav a:visited, a:link {
  color: #607d8b;
}

nav a:hover {
  color: #039be5;
  background-color: #cfd8dc;
}

nav a.active {
  color: #039be5;
}
 

添加仪表板视图

ng generate component dashboard

每次添加组件以后app.module.ts有可能名称不一致报错,需要手动修改

import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms'; // <-- NgModel lives here
import {AppComponent} from './app.component';
import {HeroesComponent} from './heroes/heroes.component';
import {HeroDetailComponent} from './hero-detail/hero-detail.component';
import {MessagesComponent} from './messages/messages.component';
import {AppRoutingModule} from './/app-routing.module';
import {DashboardComponent} from './dashboard/dashboard.component';

@NgModule({
  // 声明HeroesComponent
  declarations: [
    AppComponent,
    HeroesComponent,
    HeroDetailComponent,
    MessagesComponent,
    DashboardComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {
  title = '王者归来';
}

dashboard.component.html

<h3>Top Heroes</h3>
<div class="grid grid-pad">
  <a *ngFor="let hero of heroes" class="col-1-4">
    <div class="module hero">
      <h4>{{hero.name}}</h4>
    </div>
  </a>
</div>

dashboard.component.ts

import { Component, OnInit } from '@angular/core';
import { Hero } from '../hero';
import { HeroService } from '../hero.service';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: [ './dashboard.component.css' ]
})
export class DashboardComponent implements OnInit {
  heroes: Hero[] = [];

  constructor(private heroService: HeroService) { }

  ngOnInit() {
    this.getHeroes();
  }

  getHeroes(): void {
    this.heroService.getHeroes()
      .subscribe(heroes => this.heroes = heroes.slice(1, 5));
  }
}

dashboard.component.css

/* DashboardComponent's private CSS styles */
[class*='col-'] {
  float: left;
  padding-right: 20px;
  padding-bottom: 20px;
}
[class*='col-']:last-of-type {
  padding-right: 0;
}
a {
  text-decoration: none;
}
*, *:after, *:before {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
h3 {
  text-align: center;
  margin-bottom: 0;
}
h4 {
  position: relative;
}
.grid {
  margin: 0;
}
.col-1-4 {
  width: 25%;
}
.module {
  padding: 20px;
  text-align: center;
  color: #eee;
  max-height: 120px;
  min-width: 120px;
  background-color: #607d8b;
  border-radius: 2px;
}
.module:hover {
  background-color: #eee;
  cursor: pointer;
  color: #607d8b;
}
.grid-pad {
  padding: 10px 0;
}
.grid-pad > [class*='col-']:last-of-type {
  padding-right: 20px;
}
@media (max-width: 600px) {
  .module {
    font-size: 10px;
    max-height: 75px; }
}
@media (max-width: 1024px) {
  .grid {
    margin: 0;
  }
  .module {
    min-width: 60px;
  }
}

添加仪表板路由

import { DashboardComponent } from './dashboard/dashboard.component';

{ path: 'dashboard', component: DashboardComponent },

添加默认路由

{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },

<a routerLink="/dashboard">Dashboard</a>

将徽章和名称包裹在一个锚元素()中,并向锚点添加一个与仪表板模板中相同的属性*ngFor<a>routerLink

heroes.component.html

<li *ngFor="let hero of heroes">
  <a routerLink="/detail/{{hero.id}}">
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </a>
</li>

修复私有样式表(heroes.component.css)以使列表看起来像以前一样

/* HeroesComponent's private CSS styles */
.heroes {
  margin: 0 0 2em 0;
  list-style-type: none;
  padding: 0;
  width: 15em;
}
.heroes li {
  position: relative;
  cursor: pointer;
  background-color: #EEE;
  margin: .5em;
  padding: .3em 0;
  height: 1.6em;
  border-radius: 4px;
}

.heroes li:hover {
  color: #607D8B;
  background-color: #DDD;
  left: .1em;
}

.heroes a {
  color: #888;
  text-decoration: none;
  position: relative;
  display: block;
  width: 250px;
}

.heroes a:hover {
  color:#607D8B;
}

.heroes .badge {
  display: inline-block;
  font-size: small;
  color: white;
  padding: 0.8em 0.7em 0 0.7em;
  background-color: #607D8B;
  line-height: 1em;
  position: relative;
  left: -1px;
  top: -4px;
  height: 1.8em;
  min-width: 16px;
  text-align: right;
  margin-right: .8em;
  border-radius: 4px 0 0 4px;
}

HeroesComponent不再使用该onSelect()方法和selectedHero属性

import {Component, OnInit} from '@angular/core';
import {HeroService} from '../hero.service';
import {Hero} from '../hero';

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
  heroes: Hero[];

  constructor(private heroService: HeroService) {
  }

  ngOnInit() {
    this.getHeroes();
  }

  getHeroes(): void {
    this.heroService.getHeroes()
      .subscribe(heroes => this.heroes = heroes);
  }
}

HeroDetailComponent需要一种新的方式来获得英雄到显示器

  • 获取创建它的路线,
  • id从路线中提取
  • id通过服务器从服务器获取英雄HeroService

ActivatedRouteHeroServiceLocation服务注入构造函数,将其值保存在私有字段中:

hero-detail.component.ts

import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {Location} from '@angular/common';

import {Hero} from '../hero';
import {HeroService} from '../hero.service';

@Component({
  selector: 'app-hero-detail',
  templateUrl: './hero-detail.component.html',
  styleUrls: ['./hero-detail.component.css']
})
export class HeroDetailComponent implements OnInit {
  hero: Hero;

  constructor(
    private route: ActivatedRoute,
    private heroService: HeroService,
    private location: Location
  ) {
  }

  ngOnInit(): void {
    this.getHero();
  }

  getHero(): void {
    const id = +this.route.snapshot.paramMap.get('id');
    this.heroService.getHero(id)
      .subscribe(hero => this.hero = hero);
  }

  goBack(): void {
    this.location.back();
  }
}

HeroService添加getHero()方法

getHero(id: number): Observable<Hero> {
  // TODO: send the message _after_ fetching the hero
  this.messageService.add(`HeroService: fetched hero id=${id}`);
  return of(HEROES.find(hero => hero.id === id));
}

HeroDetail添加返回按钮,绑定到组件的goBack()方法

<button (click)="goBack()">go back</button>

dashboard.component.html

<h3>Top Heroes</h3>
<div class="grid grid-pad">
  <a *ngFor="let hero of heroes" class="col-1-4"
     routerLink="/detail/{{hero.id}}">
    <div class="module hero">
      <h4>{{hero.name}}</h4>
    </div>
  </a>
</div>

九、http

启用HTTP服务

npm安装内存中的Web API

npm install angular-in-memory-web-api --save

生成src/app/in-memory-data.service.ts

ng generate service InMemoryData

import {InMemoryDbService} from 'angular-in-memory-web-api';
import {Hero} from './hero';
import {Injectable} from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class InMemoryDataService implements InMemoryDbService {
  createDb() {
    const heroes = [
      {id: 11, name: 'Mr. Nice'},
      {id: 12, name: 'Narco'},
      {id: 13, name: 'Bombasto'},
      {id: 14, name: 'Celeritas'},
      {id: 15, name: 'Magneta'},
      {id: 16, name: 'RubberMan'},
      {id: 17, name: 'Dynama'},
      {id: 18, name: 'Dr IQ'},
      {id: 19, name: 'Magma'},
      {id: 20, name: 'Tornado'}
    ];
    return {heroes};
  }

  // Overrides the genId method to ensure that a hero always has an id.
  // If the heroes array is empty,
  // the method below returns the initial number (11).
  // if the heroes array is not empty, the method below returns the highest
  // hero id + 1.
  genId(heroes: Hero[]): number {
    return heroes.length > 0 ? Math.max(...heroes.map(hero => hero.id)) + 1 : 11;
  }
}

创建HeroSearchComponent 

ng generate component hero-search

app.module.ts

import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {FormsModule} from '@angular/forms';
// 导入符号@angular/common/http
import {HttpClientModule} from '@angular/common/http';
// 导入HttpClientInMemoryWebApiModule的InMemoryDataService类
import {HttpClientInMemoryWebApiModule} from 'angular-in-memory-web-api';
import {InMemoryDataService} from './in-memory-data.service';

import {AppRoutingModule} from './app-routing.module';

import {AppComponent} from './app.component';
import {DashboardComponent} from './dashboard/dashboard.component';
import {HeroDetailComponent} from './hero-detail/hero-detail.component';
import {HeroesComponent} from './heroes/heroes.component';
import {HeroSearchComponent} from './hero-search/hero-search.component';
import {MessagesComponent} from './messages/messages.component';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule,
    HttpClientModule,
    // 添加HttpClientInMemoryWebApiModule到数组 中
    // The HttpClientInMemoryWebApiModule module intercepts HTTP requests
    // and returns simulated server responses.
    // Remove it when a real server is ready to receive requests.
    HttpClientInMemoryWebApiModule.forRoot(
      InMemoryDataService, {dataEncapsulation: false}
    )
  ],
  declarations: [
    AppComponent,
    DashboardComponent,
    HeroesComponent,
    HeroDetailComponent,
    MessagesComponent,
    HeroSearchComponent
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}

hero.service.ts

import {Injectable} from '@angular/core';
// 导入HTTP符号
import {HttpClient, HttpHeaders} from '@angular/common/http';

import {Observable, of} from 'rxjs';
// 导入catchError符号rxjs/operators
import {catchError, map, tap} from 'rxjs/operators';

import {Hero} from './hero';
import {MessageService} from './message.service';

const httpOptions = {
  headers: new HttpHeaders({'Content-Type': 'application/json'})
};

@Injectable({providedIn: 'root'})
export class HeroService {
  // 资源的地址定义heroesUrl表单:base/:collectionName
  private heroesUrl = 'api/heroes';  // URL to web api
  // 私有属性中注入构造函数http
  constructor(
    private http: HttpClient,
    private messageService: MessageService) {
  }

  // 通过HttpClient 获取,.pipe()方法扩展可观察结果并给它一个catchError()运算符
  /** GET heroes from the server */
  getHeroes(): Observable<Hero[]> {
    return this.http.get<Hero[]>(this.heroesUrl)
      .pipe(
        tap(_ => this.log('fetched heroes')),
        catchError(this.handleError('getHeroes', []))
      );
  }

  /** GET hero by id. Return `undefined` when id not found */
  getHeroNo404<Data>(id: number): Observable<Hero> {
    const url = `${this.heroesUrl}/?id=${id}`;
    return this.http.get<Hero[]>(url)
      .pipe(
        map(heroes => heroes[0]), // returns a {0|1} element array
        tap(h => {
          const outcome = h ? `fetched` : `did not find`;
          this.log(`${outcome} hero id=${id}`);
        }),
        catchError(this.handleError<Hero>(`getHero id=${id}`))
      );
  }

  /** GET hero by id. Will 404 if id not found */
  getHero(id: number): Observable<Hero> {
    const url = `${this.heroesUrl}/${id}`;
    return this.http.get<Hero>(url).pipe(
      tap(_ => this.log(`fetched hero id=${id}`)),
      catchError(this.handleError<Hero>(`getHero id=${id}`))
    );
  }

  /* GET heroes whose name contains search term */
  searchHeroes(term: string): Observable<Hero[]> {
    if (!term.trim()) {
      // if not search term, return empty hero array.
      return of([]);
    }
    return this.http.get<Hero[]>(`${this.heroesUrl}/?name=${term}`).pipe(
      tap(_ => this.log(`found heroes matching "${term}"`)),
      catchError(this.handleError<Hero[]>('searchHeroes', []))
    );
  }

   Save methods //

  /** POST: add a new hero to the server */
  addHero(hero: Hero): Observable<Hero> {
    return this.http.post<Hero>(this.heroesUrl, hero, httpOptions).pipe(
      tap((hero: Hero) => this.log(`added hero w/ id=${hero.id}`)),
      catchError(this.handleError<Hero>('addHero'))
    );
  }

  /** DELETE: delete the hero from the server */
  deleteHero(hero: Hero | number): Observable<Hero> {
    const id = typeof hero === 'number' ? hero : hero.id;
    const url = `${this.heroesUrl}/${id}`;

    return this.http.delete<Hero>(url, httpOptions).pipe(
      tap(_ => this.log(`deleted hero id=${id}`)),
      catchError(this.handleError<Hero>('deleteHero'))
    );
  }

  /** PUT: update the hero on the server */
  updateHero(hero: Hero): Observable<any> {
    return this.http.put(this.heroesUrl, hero, httpOptions).pipe(
      tap(_ => this.log(`updated hero id=${hero.id}`)),
      catchError(this.handleError<any>('updateHero'))
    );
  }

  /**
   * Handle Http operation that failed.
   * Let the app continue.
   * @param operation - name of the operation that failed
   * @param result - optional value to return as the observable result
   */
  private handleError<T>(operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {

      // TODO: send the error to remote logging infrastructure
      console.error(error); // log to console instead

      // TODO: better job of transforming error for user consumption
      this.log(`${operation} failed: ${error.message}`);

      // Let the app keep running by returning an empty result.
      return of(result as T);
    };
  }

  // 注射MessageService。将它包装在一个私有log()方法中
  /** Log a HeroService message with the MessageService */
  private log(message: string) {
    this.messageService.add(`HeroService: ${message}`);
  }
}

更新

hero-detail.component.ts

save(): void {
  this.heroService.updateHero(this.hero)
    .subscribe(() => this.goBack());
}

hero-detail.component.html

<button (click)="save()">save</button>

添加和删除

heroes.component.ts

import {Component, OnInit} from '@angular/core';

import {Hero} from '../hero';
import {HeroService} from '../hero.service';

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
  heroes: Hero[];

  constructor(private heroService: HeroService) {
  }

  ngOnInit() {
    this.getHeroes();
  }

  getHeroes(): void {
    this.heroService.getHeroes()
      .subscribe(heroes => this.heroes = heroes);
  }

  add(name: string): void {
    name = name.trim();
    if (!name) {
      return;
    }
    this.heroService.addHero({name} as Hero)
      .subscribe(hero => {
        this.heroes.push(hero);
      });
  }

  delete(hero: Hero): void {
    this.heroes = this.heroes.filter(h => h !== hero);
    this.heroService.deleteHero(hero).subscribe();
  }

}

heroes.component.html

<h2>My Heroes</h2>

<div>
  <label>Hero name:
    <input #heroName/>
  </label>
  <!-- (click) passes input value to add() and then clears the input -->
  <button (click)="add(heroName.value); heroName.value=''">
    add
  </button>
</div>

<ul class="heroes">
  <!--&lt;!&ndash;添加[class.selected]绑定 添加单击事件绑定&ndash;&gt;-->
  <!--<li *ngFor="let hero of heroes" [class.selected]="hero === selectedHero" (click)="onSelect(hero)">-->
  <li *ngFor="let hero of heroes">
    <a routerLink="/detail/{{hero.id}}">
      <span class="badge">{{hero.id}}</span> {{hero.name}}
    </a>
    <button class="delete" title="delete hero"
            (click)="delete(hero)">x
    </button>
  </li>
</ul>

heroes.component.css

/* HeroesComponent's private CSS styles */
.heroes {
  margin: 0 0 2em 0;
  list-style-type: none;
  padding: 0;
  width: 15em;
}
.heroes li {
  position: relative;
  cursor: pointer;
  background-color: #EEE;
  margin: .5em;
  padding: .3em 0;
  height: 1.6em;
  border-radius: 4px;
}

.heroes li:hover {
  color: #607D8B;
  background-color: #DDD;
  left: .1em;
}

.heroes a {
  color: #888;
  text-decoration: none;
  position: relative;
  display: block;
  width: 250px;
}

.heroes a:hover {
  color:#607D8B;
}

.heroes .badge {
  display: inline-block;
  font-size: small;
  color: white;
  padding: 0.8em 0.7em 0 0.7em;
  background-color: #607D8B;
  line-height: 1em;
  position: relative;
  left: -1px;
  top: -4px;
  height: 1.8em;
  min-width: 16px;
  text-align: right;
  margin-right: .8em;
  border-radius: 4px 0 0 4px;
}

button {
  background-color: #eee;
  border: none;
  padding: 5px 10px;
  border-radius: 4px;
  cursor: pointer;
  cursor: hand;
  font-family: Arial;
}

button:hover {
  background-color: #cfd8dc;
}

button.delete {
  position: relative;
  left: 194px;
  top: -32px;
  background-color: gray !important;
  color: white;
}

按名称搜索

dashboard.component.html

<app-hero-search></app-hero-search>

创建HeroSearchComponent

ng generate component hero-search

hero-search.component.html

<div id="search-component">
  <h4>Hero Search</h4>
  <!--search()通过绑定到文本框input事件的事件来调用该方法。-->
  <input #searchBox id="search-box" (input)="search(searchBox.value)"/>
  <ul class="search-result">
    <!--这$是一个表示heroes$是Observable,而不是数组的约定。-->
    <!--标识了Angular的。*ngForObservable|asyncAsyncPipe-->
    <li *ngFor="let hero of heroes$ | async">
      <a routerLink="/detail/{{hero.id}}">
        {{hero.name}}
      </a>
    </li>
  </ul>
</div>

hero-search.component.ts

import {Component, OnInit} from '@angular/core';

import {Observable, Subject} from 'rxjs';

import {
  debounceTime, distinctUntilChanged, switchMap
} from 'rxjs/operators';

import {Hero} from '../hero';
import {HeroService} from '../hero.service';

@Component({
  selector: 'app-hero-search',
  templateUrl: './hero-search.component.html',
  styleUrls: ['./hero-search.component.css']
})
export class HeroSearchComponent implements OnInit {
  // 注意声明heroes$为Observable
  heroes$: Observable<Hero[]>;
  // 该searchTerms属性被声明为RxJS Subject。
  private searchTerms = new Subject<string>();

  constructor(private heroService: HeroService) {
  }

  // Push a search term into the observable stream.
  search(term: string): void {
    this.searchTerms.next(term);
  }

  ngOnInit(): void {
    this.heroes$ = this.searchTerms.pipe(
      // 等待直到新字符串事件的流程在传递最新字符串之前暂停300毫秒
      // wait 300ms after each keystroke before considering the term
      debounceTime(300),
      // 确保仅在过滤器文本更改时才发送请求
      // ignore new term if same as previous term
      distinctUntilChanged(),
      // 它取消并丢弃先前的搜索可观察量,仅返回可观察的最新搜索服务。
      // switch to new search observable each time the term changes
      switchMap((term: string) => this.heroService.searchHeroes(term)),
    );
  }
}

hero-search.component.css

/* HeroSearch private styles */
.search-result li {
  border-bottom: 1px solid gray;
  border-left: 1px solid gray;
  border-right: 1px solid gray;
  width: 195px;
  height: 16px;
  padding: 5px;
  background-color: white;
  cursor: pointer;
  list-style-type: none;
}

.search-result li:hover {
  background-color: #607D8B;
}

.search-result li a {
  color: #888;
  display: block;
  text-decoration: none;
}

.search-result li a:hover {
  color: white;
}
.search-result li a:active {
  color: white;
}
#search-box {
  width: 200px;
  height: 20px;
}


ul.search-result {
  margin-top: 0;
  padding-left: 0;
}

十、集成bootstrap和jasper报表

安装bootstrap

npm i bootstrap -s 

导入bootstrap样式

将目录下的 ../node_modules/bootstrap/dist/css/bootstrap.min.css 添加到项目的angular.json文件的styles中

创建报表组件

ng generate component report

report.component.ts

import {Component, OnInit} from '@angular/core';
import {ReportService} from "../services/report.service";
import {DomSanitizer} from "@angular/platform-browser";

@Component({
  selector: 'app-report',
  templateUrl: './report.component.html',
  styleUrls: ['./report.component.css']
})
export class ReportComponent implements OnInit {
  reportSrc: string;
  imgsrc = 'https://c.staticblitz.com/assets/client/components/SideMenu/blitz_logo-11cebad97cad4b50bc955cf72f532d1b.png';

  constructor(public reportService: ReportService, public sanitizer: DomSanitizer) {
  }

  ngOnInit() {
    this.reportChange("crosstab");
  }

  fileChange(e): void {
    const file = e.srcElement.files[0]; // 获取图片这里只操作一张图片
    this.imgsrc = window.URL.createObjectURL(file); // 获取上传的图片临时路径
  }

  reportChange(name: string): void {
    this.reportSrc = 'http://localhost:8889/' + name + '?whereSql=cost%3C15&inline=true';
  }
}

report.component.html

<div class="container">
  <h2>报表实例</h2>
  <div class="container-fluid">
    <nav class="breadcrumb">
      <button class="clear"
              (click)="reportChange('product')">product
      </button>
      <button class="clear"
              (click)="reportChange('crosstab')">crosstab
      </button>
    </nav>
    <div class="row">
      <div class="col-md-3 bg-success">
        <p>上传图片显示缩略图</p>
        <img height="100px" width="100px" [src]="sanitizer.bypassSecurityTrustUrl(imgsrc)">
        <input type="file" (change)="fileChange($event)">
      </div>
      <div class="col-md-9 bg-warning">
        <iframe [src]="sanitizer.bypassSecurityTrustResourceUrl(reportSrc)" class="report"></iframe>
      </div>
    </div>
  </div>
</div>

展示效果

代码:https://github.com/glory2018/moses-angular.git

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值