• 使用angular4和asp.net core 2 web api做个练习项目(二), 这部分都是angular


    上一篇: http://www.cnblogs.com/cgzl/p/7755801.html

    完成client.service.ts:

    import { Injectable } from '@angular/core';
    import { Http, Headers } from '@angular/http';
    import { Observable } from 'rxjs/Observable';
    import { ErrorHandler } from '@angular/core';
    import 'rxjs/add/operator/map';
    import 'rxjs/add/operator/catch';
    import 'rxjs/add/observable/throw';
    
    import { Client } from '../models/Client';
    
    @Injectable()
    export class ClientService {
      private url = 'http://localhost:5001/api/client';
      private headers = new Headers({ 'Content-Type': 'application/json' });
    
      constructor(private http: Http) { }
    
      getAll(): Observable<Client[]> {
        return this.http.get(this.url)
          .map(response => response.json() as Client[]);
      }
    
      getOne(id: number): Observable<Client> {
        return this.http.get(`${this.url}/${id}`)
          .map(response => response.json() as Client);
      }
    
      create(client: Client) {
        return this.http.post(this.url, JSON.stringify(client), { headers: this.headers })
          .map(response => response.json())
          .catch(this.handleError);
      }
    
      update(client: Client) {
        return this.http.patch(`${this.url}/${client.id}`, JSON.stringify(client), { headers: this.headers })
          .map(response => response.json())
          .catch(this.handleError);
      }
    
      delete(id: number) {
        return this.http.delete(`${this.url}/${id}`)
          .map(response => response.json())
          .catch(this.handleError);
      }
    
      private handleError(error: Response) {
        if (error.status === 400) {
          return Observable.throw('Bad Request');
        }
    
        if (error.status === 404) {
          return Observable.throw('Not Found');
        }
        return Observable.throw('Error Occurred');
      }
    }

    我个人比较喜欢 observable的方式而不是promise.

    然后再Client.Component里面, 注入ClientService, 在NgOnInit里面调用查询方法:

    import { Component, OnInit } from '@angular/core';
    import { ClientService } from '../../services/client.service';
    import { Client } from '../../models/Client';
    
    @Component({
      selector: 'app-clients',
      templateUrl: './clients.component.html',
      styleUrls: ['./clients.component.css']
    })
    export class ClientsComponent implements OnInit {
    
      public clients: Client[];
    
      constructor(private service: ClientService) { }
    
      ngOnInit() {
        this.service.getAll().subscribe(
          clients => {
          this.clients = clients;
            console.log(this.clients);
          }
        );
      }
    }

    然后修改Client.Component.html:

    <table class="table table-striped" *ngIf="clients?.length > 0; else noClients">
      <thead class="thead-dark">
        <tr>
          <th>ID</th>
          <th>Name</th>
          <th>Email</th>
          <th>Balance</th>
          <th></th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let client of clients">
          <td>{{client.id}}</td>
          <td>{{client.firstName + ' ' + client.lastName}}</td>
          <td>{{client.email}}</td>
          <td>{{client.balance}}</td>
          <td><a href="" class="btn btn-secondary btn-sm">明细</a></td>
        </tr>
      </tbody>
    </table>
    <ng-template #noClients>
      <hr>
      <h5>系统中没有客户..</h5>
    </ng-template>

    然后把client.component放在dashboard中:

    dashboard.component.html:

    <app-clients></app-clients>

    然后看看浏览器:

    我这里还没有数据, 如果有数据的话, 将会显示一个table, header是黑色的.

    使用font-awesome

    npm install font-awesome --save

    然后打开.angular-cli.json:

          "styles": [
            "styles.css",
            "../node_modules/bootstrap/dist/css/bootstrap.css",
            "../node_modules/font-awesome/css/font-awesome.css"
          ],
          "scripts": [
            "../node_modules/jquery/dist/jquery.js",
            "../node_modules/tether/dist/js/tether.js",
            "../node_modules/bootstrap/dist/js/bootstrap.bundle.js"
          ]

    重新运行ng serve

    修改 client.component.html的明细按钮:

    <td><a href="" class="btn btn-secondary btn-sm"><i class="fa fa-arrow-circle-o-right"></i> 明细</a></td>

    然后还是使用swagger添加两条数据吧: http://localhost:5001/swagger, 现在的效果:

    添加一个总计:

    import { Component, OnInit } from '@angular/core';
    import { ClientService } from '../../services/client.service';
    import { Client } from '../../models/Client';
    
    @Component({
      selector: 'app-clients',
      templateUrl: './clients.component.html',
      styleUrls: ['./clients.component.css']
    })
    export class ClientsComponent implements OnInit {
    
      public clients: Client[];
      public total: number;
    
      constructor(private service: ClientService) { }
    
      ngOnInit() {
        this.service.getAll().subscribe(
          clients => {
          this.clients = clients;
          this.getTotal();
          }
        );
      }
    
      getTotal() {
        this.total = this.clients.reduce((previous, current) => previous + current.balance, 0);
      }
    }

    html:

    <div class="row">
      <div class="col-md-6">
        <h2>
          <i class="fa fa-users">客户</i>
        </h2>
      </div>
      <div class="col-md-6">
        <h5 class="pull-right text-muted">
          总计: {{total | currency:"USD":true}}
        </h5>
      </div>
    </div>
    <table class="table table-striped" *ngIf="clients?.length > 0; else noClients">
      <thead class="thead-dark">
        <tr>
          <th>ID</th>
          <th>Name</th>
          <th>Email</th>
          <th>Balance</th>
          <th></th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let client of clients">
          <td>{{client.id}}</td>
          <td>{{client.firstName + ' ' + client.lastName}}</td>
          <td>{{client.email}}</td>
          <td>{{client.balance}}</td>
          <td>
            <a href="" class="btn btn-secondary btn-sm">
              <i class="fa fa-arrow-circle-o-right"></i> 明细</a>
          </td>
        </tr>
      </tbody>
    </table>
    <ng-template #noClients>
      <hr>
      <h5>系统中没有客户..</h5>
    </ng-template>

    Sidebar 侧边栏

    打开sidebar.component.html:

    <a routerLink="/add-client" href="#" class="btn btn-success btn-block"><i class="fa fa-plus"></i>添加新客户</a>

    然后再dashboard中添加sidebar:

    <div class="row">
        <div class="col-md-10">
            <app-clients></app-clients>
        </div>
        <div class="col-md-2">
            <app-sidebar></app-sidebar>
        </div>
    </div>

    添加在了右边. 效果如图:

    然后需要在app.module.ts里面添加路由:

    const appRoutes: Routes = [
      { path: '', component: DashboardComponent },
      { path: 'register', component: RegisterComponent },
      { path: 'login', component: LoginComponent },
      { path: 'add-client', component: AddClientComponent }
    ];

    Add-Client 添加客户的表单:

    打开add-client.component.html:

    <div class="row">
      <div class="col-md-6">
        <a routerLink="/" href="#" class="btn btn-link"><i class="fa fa-arrow-circle-o-left"></i> 回到Dashboard </a>
      </div>
      <div class="col-md-6">
    
      </div>
    </div>
    
    <div class="card">
      <div class="card-header">
        Add Client
      </div>
      <div class="card-body">
        <form #f="ngForm" (ngSubmit)="onSubmit(f)">
          <div class="form-group">
            <label for="firstName"></label>
            <input 
              type="text" 
              class="form-control" 
              [(ngModel)]="client.firstName"
              name="firstName"
              #clientFirstName="ngModel"
              minlength="2"
              required>
            <div *ngIf="clientFirstName.errors.required && clientFirstName.touched" class="alter alert-danger">
              名字是必填的
            </div>
            <div *ngIf="clientFirstName.errors.minlength && clientFirstName.touched" class="alter alert-danger">
              名字最少是两个字
            </div>
          </div>
        </form>
      </div>
    </div>

    现在表单里面添加一个字段, 然后在app.module里面添加FormsModule:

    import { FormsModule } from '@angular/forms';
    
      imports: [
        BrowserModule,
        RouterModule.forRoot(appRoutes),
        HttpModule,
        FormsModule
      ],

    现在应该是这个样子:

    然后把表单都完成 add-client.component.html:

    <div class="row">
      <div class="col-md-6">
        <a routerLink="/" href="#" class="btn btn-link">
          <i class="fa fa-arrow-circle-o-left"></i> 回到Dashboard </a>
      </div>
      <div class="col-md-6">
    
      </div>
    </div>
    
    <div class="card">
      <div class="card-header">
        添加客户
      </div>
      <div class="card-body">
        <form #f="ngForm" (ngSubmit)="onSubmit(f)" novalidate>
          <div class="form-group">
            <label for="firstName"></label>
            <input type="text" class="form-control" [(ngModel)]="client.firstName" name="firstName" #clientFirstName="ngModel" minlength="2"
              required>
            <div *ngIf="clientFirstName.touched && clientFirstName.invalid">
              <div *ngIf="clientFirstName.errors.required" class="alert alert-danger">
                名字是必填的
              </div>
              <div *ngIf="clientFirstName.errors.minlength" class="alert alert-danger">
                名字最少是两个字
              </div>
            </div>
          </div>
          <div class="form-group">
            <label for="lastName"></label>
            <input type="text" class="form-control" [(ngModel)]="client.lastName" name="lastName" #clientLastName="ngModel" minlength="2"
              required>
            <div *ngIf="clientLastName.touched && clientLastName.invalid">
              <div *ngIf="clientLastName.errors.required" class="alert alert-danger">
                姓是必填的
              </div>
              <div *ngIf="clientLastName.errors.minlength" class="alert alert-danger">
                姓最少是两个字
              </div>
            </div>
          </div>
          <div class="form-group">
            <label for="email">Email</label>
            <input type="email" class="form-control" [(ngModel)]="client.email" name="email" #clientEmail="ngModel" required>
            <div *ngIf="clientEmail.touched && clientEmail.invalid">
              <div *ngIf="clientEmail.errors.required" class="alert alert-danger">
                Email是必填的
              </div>
            </div>
          </div>
          <div class="form-group">
            <label for="phone">联系电话</label>
            <input type="text" class="form-control" [(ngModel)]="client.phone" name="phone" #clientPhone="ngModel" minlength="10">
            <div *ngIf="clientPhone.touched && clientPhone.invalid">
              <div *ngIf="clientPhone.errors.minlength" class="alert alert-danger">
                电话最少是10位
              </div>
            </div>
          </div>
          <div class="form-group">
            <label for="balance">余额</label>
            <input type="number" class="form-control" [(ngModel)]="client.balance" name="balance" #clientBalance="ngModel" [disabled]="disableBalanceOnAdd">
          </div>
          <input type="submit" class="btn btn-primary btn-block" value="提交">
        </form>
      </div>
    </div>

    现在看起来是这样:

    再安装一个库: npm install --save angular2-flash-messages

    这个库可以略微灵活的显示提示信息.

    npm install --save angular2-flash-messages

    在app.module里面:

    import { FlashMessagesModule } from 'angular2-flash-messages';
    
      imports: [
        BrowserModule,
        RouterModule.forRoot(appRoutes),
        HttpModule,
        FormsModule,
        FlashMessagesModule
      ],

    add-client.component.ts:

    import { Component, OnInit } from '@angular/core';
    import { FlashMessagesService } from 'angular2-flash-messages';
    import { Router } from '@angular/router';
    import { Client } from '../../models/Client';
    
    @Component({
      selector: 'app-add-client',
      templateUrl: './add-client.component.html',
      styleUrls: ['./add-client.component.css']
    })
    export class AddClientComponent implements OnInit {
    
      public client: Client = {
        id: 0,
        firstName: '',
        lastName: '',
        email: '',
        phone: '',
        balance: 0
      };
    
      public disableBalanceOnAdd = true;
    
      constructor(
        public flashMessagesService: FlashMessagesService,
        public router: Router
      ) { }
    
      ngOnInit() {
      }
    
      onSubmit({ value, valid }: { value: Client, valid: boolean }) {
        if (!valid) {
          this.flashMessagesService.show('请正确输入表单', { cssClass: 'alert alert-danger', timeout: 4000 });
          this.router.navigate(['/add-client']);
        } else {
          console.log('valid');
        }
      }
    }

    然后需要在某个地方放置flash messages, 打开app.component.html:

    <app-navbar></app-navbar>
    <div class="container">
      <flash-messages></flash-messages>
      <router-outlet></router-outlet>
    </div>

    然后运行一下:

    大约这个样子.

    然后修改提交, 注入clientService, 把数据新增到web api:

    import { Component, OnInit } from '@angular/core';
    import { FlashMessagesService } from 'angular2-flash-messages';
    import { Router } from '@angular/router';
    import { Client } from '../../models/Client';
    import { ClientService } from '../../services/client.service';
    
    @Component({
      selector: 'app-add-client',
      templateUrl: './add-client.component.html',
      styleUrls: ['./add-client.component.css']
    })
    export class AddClientComponent implements OnInit {
    
      public client: Client = {
        id: 0,
        firstName: '',
        lastName: '',
        email: '',
        phone: '',
        balance: 0
      };
    
      public disableBalanceOnAdd = true;
    
      constructor(
        public flashMessagesService: FlashMessagesService,
        public router: Router,
        public clientService: ClientService
      ) { }
    
      ngOnInit() {
      }
    
      onSubmit({ value, valid }: { value: Client, valid: boolean }) {
        if (this.disableBalanceOnAdd) {
          value.balance = 0;
        }
        if (!valid) {
          this.flashMessagesService.show('请正确输入表单', { cssClass: 'alert alert-danger', timeout: 4000 });
          this.router.navigate(['/add-client']);
        } else {
          this.clientService.create(value).subscribe(
            client => {
              console.log(client);
              this.flashMessagesService.show('新客户添加成功', { cssClass: 'alert alert-success', timeout: 4000 });
              this.router.navigate(['/']);
            }
          );
        }
      }
    }

    可以运行试试. 应该是好用的.

    Client Detail 客户明细:

    首先在app.module.ts里面添加路由:

    const appRoutes: Routes = [
      { path: '', component: DashboardComponent },
      { path: 'register', component: RegisterComponent },
      { path: 'login', component: LoginComponent },
      { path: 'add-client', component: AddClientComponent },
      { path: 'client/:id', component: ClientDetailsComponent }
    ];

    然后在clients.componet.html修改:

          <td>
            <a href="" [routerLink]="['/client', client.id]" class="btn btn-secondary btn-sm">
              <i class="fa fa-arrow-circle-o-right"></i> 明细</a>
          </td>

    修改client-detail.component.ts:

    import { Component, OnInit } from '@angular/core';
    import { ClientService } from '../../services/client.service';
    import { FlashMessagesService } from 'angular2-flash-messages';
    import { Router, ActivatedRoute, Params } from '@angular/router';
    import { Client } from '../../models/Client';
    
    @Component({
      selector: 'app-client-details',
      templateUrl: './client-details.component.html',
      styleUrls: ['./client-details.component.css']
    })
    export class ClientDetailsComponent implements OnInit {
    
      id: string;
      client: Client;
      hasBalance = false;
      showBalanceUpdateInput = false;
    
      constructor(
        public clientService: ClientService,
        public router: Router,
        public route: ActivatedRoute,
        public flashMessagesService: FlashMessagesService
      ) { }
    
      ngOnInit() {
        // 获取ID
        this.id = this.route.snapshot.params['id'];
        // 获取Client
        this.clientService.getOne(+this.id).subscribe(
          client => {
            if (client.balance > 0) {
              this.hasBalance = true;
            }
            this.client = client;
          }
        );
      }
    
    }

    然后修改html:

    <div class="row">
      <div class="col-md-6">
        <a routerLink="/" class="btn btn-link">
          <i class="fa fa-arrow-circle-o-left"></i> 回到Dashboard</a>
      </div>
      <div class="col-md-6">
        <div class="btn-group pull-right">
          <a [routerLink]="['/edit-client', id]" class="btn btn-secondary">编辑</a>
          <button type="button" class="btn btn-danger" (click)="onDeleteClick()">删除</button>
        </div>
      </div>
    </div>
    <hr>
    <div class="card" *ngIf="client">
      <div class="card-header">
        <h3> {{client.firstName + ' ' + client.lastName}}</h3>
      </div>
      <div class="card-body">
        <div class="row">
          <div class="col-md-8">
            <h4>客户ID: {{id}}</h4>
          </div>
          <div class="col-md-4">
            <h4 class="pull-right">
              余额:
              <span [class.text-danger]="!hasBalance" [class.text-success]="hasBalance">
                {{client.balance | currency: 'USD': true}}
              </span>
              <small>
                <a (click)="showBalanceUpdateInput = !showBalanceUpdateInput"><i class="fa fa-pencil"></i></a>
              </small>
            </h4>
            <div class="clearfix">
              <form *ngIf="showBalanceUpdateInput" (submit)="updateBalance(id)" class="form-inline pull-right">
                <div class="form-group">
                  <input type="number" class="form-control" name="balance" [(ngModel)]="client.balance">
                </div>
                <button type="submit" class="btn btn-primary">
                  更新
                </button>
              </form>
            </div>
          </div>
        </div>
        <hr>
        <ul class="list-group">
          <li class="list-group-item">
            Email: {{client.email}}
          </li>
          <li class="list-group-item">
            联系电话: {{client.phone}}
          </li>
        </ul>
      </div>
    </div>

    然后要做一个修改余额的动作, 这是个部分更新, 应该对应http patch.

    目前client.service里没有patch, 所以需要添加一个patch方法, 不过首先建立一个PatchModel.ts:.

    export interface PatchModel {
        op: string;
        path: string;
        value: any;
    }

    client.service.ts:

    import { PatchModel } from '../models/PatchModel';
    
    
      patch(id: number, patchs: PatchModel[]) {
        return this.http.patch(`${this.url}/${id}`, JSON.stringify(patchs), { headers: this.headers })
          .map(response => response.json())
          .catch(this.handleError);
      }

    然后修改 client-detail.component.ts:

    import { PatchModel } from '../../models/PatchModel';
    
      updateBalance(id: string) {
        // 更新客户的余额
        this.clientService.patch(+id, [{ op: 'replace', path: '/balance', value: this.client.balance }])
          .subscribe(() => {
            this.showBalanceUpdateInput = false;
            this.flashMessagesService.show('更新余额成功', { cssClass: 'alert alert-success', timeout: 4000 });
          });
      }

    运行一下, 应该好用:

    删除动作:

      onDeleteClick() {
        if (confirm('确定要删除?')) {
          this.clientService.delete(+this.id).subscribe(() => {
            this.flashMessagesService.show('客户删除成功', { cssClass: 'alert alert-success', timeout: 4000 });
            this.router.navigate(['/']);
          });
        }
      }

    应该好用, 删除后跳转到dashboard.

    编辑客户 Edit-Client

     先添加路由 app.module.ts:

    const appRoutes: Routes = [
      { path: '', component: DashboardComponent },
      { path: 'register', component: RegisterComponent },
      { path: 'login', component: LoginComponent },
      { path: 'add-client', component: AddClientComponent },
      { path: 'client/:id', component: ClientDetailsComponent },
      { path: 'edit-client/:id', component: EditClientComponent }
    ];

    然后修改edit-client.component.html:

    <div class="row">
        <div class="col-md-6">
          <a [routerLink]="['/client', id]" href="#" class="btn btn-link">
            <i class="fa fa-arrow-circle-o-left"></i> 回到客户明细 </a>
        </div>
        <div class="col-md-6">
      
        </div>
      </div>
      
      <div class="card">
        <div class="card-header">
          编辑客户
        </div>
        <div class="card-body">
          <form #f="ngForm" (ngSubmit)="onSubmit(f)" *ngIf="client" novalidate>
            <div class="form-group">
              <label for="firstName"></label>
              <input type="text" class="form-control" [(ngModel)]="client.firstName" name="firstName" #clientFirstName="ngModel" minlength="2"
                required>
              <div *ngIf="clientFirstName.touched && clientFirstName.invalid">
                <div *ngIf="clientFirstName.errors.required" class="alert alert-danger">
                  名字是必填的
                </div>
                <div *ngIf="clientFirstName.errors.minlength" class="alert alert-danger">
                  名字最少是两个字
                </div>
              </div>
            </div>
            <div class="form-group">
              <label for="lastName"></label>
              <input type="text" class="form-control" [(ngModel)]="client.lastName" name="lastName" #clientLastName="ngModel" minlength="2"
                required>
              <div *ngIf="clientLastName.touched && clientLastName.invalid">
                <div *ngIf="clientLastName.errors.required" class="alert alert-danger">
                  姓是必填的
                </div>
                <div *ngIf="clientLastName.errors.minlength" class="alert alert-danger">
                  姓最少是两个字
                </div>
              </div>
            </div>
            <div class="form-group">
              <label for="email">Email</label>
              <input type="email" class="form-control" [(ngModel)]="client.email" name="email" #clientEmail="ngModel" required>
              <div *ngIf="clientEmail.touched && clientEmail.invalid">
                <div *ngIf="clientEmail.errors.required" class="alert alert-danger">
                  Email是必填的
                </div>
              </div>
            </div>
            <div class="form-group">
              <label for="phone">联系电话</label>
              <input type="text" class="form-control" [(ngModel)]="client.phone" name="phone" #clientPhone="ngModel" minlength="10">
              <div *ngIf="clientPhone.touched && clientPhone.invalid">
                <div *ngIf="clientPhone.errors.minlength" class="alert alert-danger">
                  电话最少是10位
                </div>
              </div>
            </div>
            <div class="form-group">
              <label for="balance">余额</label>
              <input type="number" class="form-control" [(ngModel)]="client.balance" name="balance" #clientBalance="ngModel" [disabled]="disableBalanceOnEdit">
            </div>
            <input type="submit" class="btn btn-primary btn-block" value="提交">
          </form>
        </div>
      </div>
      

    修改edit-client.component.ts:

    import { Component, OnInit } from '@angular/core';
    import { ClientService } from '../../services/client.service';
    import { FlashMessagesService } from 'angular2-flash-messages';
    import { Router, ActivatedRoute, Params } from '@angular/router';
    import { Client } from '../../models/Client';
    
    @Component({
      selector: 'app-edit-client',
      templateUrl: './edit-client.component.html',
      styleUrls: ['./edit-client.component.css']
    })
    export class EditClientComponent implements OnInit {
    
      id: string;
      client: Client;
      disableBalanceOnEdit = true;
    
      constructor(
        public clientService: ClientService,
        public router: Router,
        public route: ActivatedRoute,
        public flashMessagesService: FlashMessagesService
      ) { }
    
      ngOnInit() {
        // 获取ID
        this.id = this.route.snapshot.params['id'];
        // 获取Client
        this.clientService.getOne(+this.id).subscribe(
          client => {
            this.client = client;
          }
        );
      }
      onSubmit({ value, valid }: { value: Client, valid: boolean }) {
        if (!valid) {
          this.flashMessagesService.show('请正确输入表单', { cssClass: 'alert alert-danger', timeout: 4000 });
          this.router.navigate(['/edit-client', this.id]);
        } else {
          this.clientService.update(+this.id, value).subscribe(
            client => {
              console.log(client);
              this.flashMessagesService.show('更新客户成功', { cssClass: 'alert alert-success', timeout: 4000 });
              this.router.navigate(['/client', this.id]);
            }
          );
        }
      }
    }

    client.service.ts需要修改一下, 之前的update方法写的不正确也不符合规范:

      update(id: number, client: Client) {
        return this.http.put(`${this.url}/${id}`, JSON.stringify(client), { headers: this.headers })
          .map(response => response.json())
          .catch(this.handleError);
      }

    然后运行, 好用.

    先写到这, 估计还得写一篇, 下一篇文章里面要使用identity server 4了, implicit grant flow.

  • 相关阅读:
    Python数据爬虫,爬链家的二手房信息
    驼峰命名法
    变量
    use strict(变得严格)
    注释
    分号(line break:分行符号)
    使用外部js文件
    confirm
    prompt
    https和http的区别
  • 原文地址:https://www.cnblogs.com/cgzl/p/7763397.html
Copyright © 2020-2023  润新知