Angular Http服务通讯实战

实战对象:股票列表展示和修改表单,前端采用angular,后端采用php

第一步:后端代码实现【angular/index.php】:获取数据

<?php 

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");

 $type=$_GET['type'];
 $id=$_GET['id'];

  $stocks=[
    ['id'=>1,'name'=>"第一支股票",'price'=>1.99,'rating'=>3.5,'desc'=>"這是第一隻股票呵呵噠",'categories'=>["金融","互聯網"]],
    ['id'=>2,'name'=>"第二支股票",'price'=>2.99,'rating'=>2.5,'desc'=>"這是第二隻股票呵呵噠",'categories'=>["金融","互聯網"]],
    ['id'=>3,'name'=>"第三支股票",'price'=>3.99,'rating'=>3,'desc'=>"這是第三隻股票呵呵噠",'categories'=>["金融","IT"]],
    ['id'=>4,'name'=>"第四支股票",'price'=>4.99,'rating'=>2,'desc'=>"這是第四隻股票呵呵噠",'categories'=>["互聯網"]],
  ];

  function getStocks($stocks,$type,$id){
      if(empty($type)){
        echo json_encode(['state'=>0,'msg'=>'请求路径错误,没有type参数']);
      }
     if($type=="list"){
        echo json_encode($stocks);
     }else if($type=="form"){
        
        for($i=0;$i<count($stocks);$i++){
            if($stocks[$i]['id']==$id){
                echo json_encode($stocks[$i]);
                break;
            }
        }
        
     }
  }
  getStocks($stocks,$type,$id);
?>

第二步:前端在服务【stock.service.ts】中发送http请求,获取数据

import { Injectable } from '@angular/core';
import { Http,Response } from '@angular/http';
import { Observable } from 'rxjs';

@Injectable()
export class StockService {
  private stocks:Observable<Object>;
  constructor(private http:Http) { }
  //获取列表数据
  getStocks():Observable<Stock[]>{
    return this.http.get("http://localhost/angular/index.php?type=list").map(res=>res.json());
    }
  //获取单个表单数据
 getStock(id:number):Observable<Stock> {
    return this.http.get("http://localhost/angular/index.php?type=form&id="+id).map(res=>res.json());
  }

}

export class Stock{
  constructor(
    public id:number,
    public name:string,
    public price:number,
    public rating:number,
    public desc:string,
    public categories:Array<string>
    ){

  }
}

第三步【##1】:在列表组件【stock-manage.component.ts】获取服务中获取的数据

import {FormControl} from '@angular/forms';
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import {  StockService, Stock } from '../../stock.service';
import 'rxjs/Rx';
import { Observable } from 'rxjs';
@Component({
  selector: 'app-stock-manage',
  templateUrl: './stock-manage.component.html',
  styleUrls: ['./stock-manage.component.css']
})
export class StockManageComponent implements OnInit {

  private stocks:Observable<Stock[]>;//定义一个变量,接收流类型的数据,且知此处使用的是异步管道处理返回的流数据
  constructor(private stockService:StockService) { }

  ngOnInit() {  //頁面初始化的時候會被調用的方法
   this.stocks=this.stockService.getStocks(); //此处调用服务中的数据
  }
}

第三步【##2】:在列表组件模板【stock-manage.component.html】中用异步管道处理流数据

         <table class="table table-bordered">
      <tr>
        <th>#</th>
        <th >股票名称</th>
        <th>价格</th>
        <th>评级</th>
        <th >操作</th>
      </tr>
      <tr *ngFor="let stock of stocks | async|stockFilter:'name':keyword;let i=index">
        <td>{{i+1}}</td>
        <td>{{stock.name}}</td>
        <td>{{stock.price}}</td>
        <td>
           <app-stars [rating]="stock.rating"></app-stars>
        </td>
        <td>
        <a class="btn btn-warning btn-xs" href="javascript:;" (click)="update(stock)" >
        <span class="glyphicon glyphicon-pencil"></span>修改</a> 
        <a  class="btn btn-danger btn-xs"  href="#"><span class="glyphicon glyphicon-remove"></span>删除</a>
        </td>
      </tr>
     
    </table>

第四步【##1】:修改表单组件中【stock-form.component.ts】获取服务的数据

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { StockService, Stock } from '../../stock.service';
import { FormGroup, FormBuilder, Validators, FormControl, FormArray } from '@angular/forms';

@Component({
  selector: 'app-stock-form',
  templateUrl: './stock-form.component.html',
  styleUrls: ['./stock-form.component.css']
})
export class StockFormComponent implements OnInit {
  public stock=new Stock(0,"",0,0,"",[]); //初始化表单对象,用以等待http请求返回结果,以免报错
  constructor(private routerinfo:ActivatedRoute,private stockService:StockService,private router:Router) { }
  //创建表单模型对象,让angular来接管表单处理
  private formModel:FormGroup;  //并且要将当前这个属性绑定到模板中form标签的[formGroup]指令上
  private categories=["IT","互聯網",'金融'];   //股票类型初始化,原始数据,并将其绑定到模板
  ngOnInit() {


      let stockid=this.routerinfo.snapshot.params["id"];
        //声明数据结构
        let fb=new FormBuilder();
        this.formModel=fb.group({
          name:['',[Validators.required,Validators.minLength(3)]],  
        //将name绑定到模板页面的formControlName上:formControlName="name"
          price:['',Validators.required],
          desc:[''],
          categories:fb.array([     //用法原因:股票的类型在定义的时候就是string的数组Array<string>,[true,true,null]
            //this.stock.categories.indexOf(this.categories[0])!=-1 this.stock.categories里面有IT就返回true
            new FormControl(false),
            new FormControl(false),
            new FormControl(false),
          ],this.categoriesSelectValidator)
        });

      if(stockid!=0){
        this.stockService.getStock(stockid).subscribe(
          data=>{
            this.stock=data;
            console.log(data);
            this.formModel.reset({
              name:data.name,
              price:data.price,
              desc:data.desc,
              categories:[
                data.categories.indexOf(this.categories[0])!=-1,
                data.categories.indexOf(this.categories[1])!=-1,
                data.categories.indexOf(this.categories[2])!=-1,
              ]
            })
          }

        );

      }else{
        this.stock=new Stock(0,"",0,0,"",[]);
      }
     
    

  }

  save(){
    //1.rating的处理,
    this.formModel.value.rating=this.stock.rating;
    //2 将股票类型转换为汉字
    var categoriesChainese=[];
    var index=0;
    for(var i=0;i<3;i++){
      if(this.formModel.value.categories[i]){  //说明当前项被选中,就将其转为汉字
        categoriesChainese[index++]=this.categories[i]
      }
      
    }
    this.formModel.value.categories=categoriesChainese;

    //打印出表单数据模型
    console.log(this.formModel.value);
    //this.router.navigate(['/stock']);
  }

  //股票类型校验器
  categoriesSelectValidator(control:FormArray):any{
    //
    var valid=false;
    control.controls.forEach(control=>{
      if(control.value){
         valid=true
      }
    });

    if(valid){
      return null;
    }else{
      return {categoriesLength:true};
    }
    
  }

}

第四步【##2】:修改表单组件中模板【stock-form.component.html】展示获取的数据,和原来一样不用修改

<p>
 {{stock.name}}
</p>

  <!-- Horizontal Form -->
  <div class="box box-info">
    <div class="box-header with-border">
      <h3 class="box-title">股票信息</h3>
    </div>
    <!-- /.box-header -->
    <!-- form start -->
    <form class="form-horizontal" [formGroup]="formModel">
      <div class="box-body">

        <!-- ##校验name -->
        <div class="form-group" [class.has-error]="formModel.get('name').touched && 
            (formModel.hasError('minlength','name')||formModel.hasError('required','name'))">
            <label for="name" class="col-sm-2 control-label">股票名称</label>
            <div class="col-sm-6">
              <input type="text" class="form-control" formControlName="name" id="name" placeholder="股票名称" >
            </div>
            <span class="help-block"    [class.hidden]="formModel.get('name').untouched||
            !formModel.hasError('required','name')" >股票名称是必填项!</span>
            <span class="help-block" [class.hidden]="formModel.get('name').untouched||
            !formModel.hasError('minlength','name')">股票名称长度至少3位!</span>
        </div>

      <!-- ##校验price -->
        <div class="form-group"  [class.has-error]="formModel.get('price').touched &&
             formModel.hasError('required','price')">
          <label for="price" class="col-sm-2 control-label"  >股票价格</label>

          <div class="col-sm-6">
            <input type="text" class="form-control" id="price"  formControlName="price" placeholder="股票价格">
          </div>
          <span class="help-block"    [class.hidden]="formModel.get('price').untouched||
            !formModel.hasError('required','price')" >股票价格是必填项!</span>
        </div>

        <div class="form-group">
          <label for="price" class="col-sm-2 control-label">股票评级</label>

          <div class="col-sm-10">
            <app-stars [(rating)]="stock.rating"></app-stars>
          </div>
        </div>
        <div class="form-group">
          <label for="price" class="col-sm-2 control-label"  >股票描述</label>

          <div class="col-sm-10">
           <textarea  class="form-control" formControlName="desc" placeholder="股票描述"></textarea>
          </div>
        </div>
 <!-- ##校验categories 自定义校验器 -->
        <!-- 【1】将整个checkbox组绑定到后台的categories -->
        <div class="form-group" formArrayName="categories"  [class.has-error]="formModel.get('categories').touched &&
             formModel.hasError('categoriesLength','categories')" >
          <label for="categories" class="col-sm-2 control-label"  >股票类型</label>
          <!-- 【2】循环初始化数组categories -->
          <div *ngFor="let category of categories;let i=index;" class=" col-sm-2">
            <div class="checkbox ">
              <label>
                <!-- 【3】将每个checkbox绑定到categories的每个项,因为是绑定到变量上所以加[formControlName] -->
                <input [formControlName]='i' type="checkbox"  > {{category}}
              </label>
            </div>
          </div>
          <span class="help-block"    [class.hidden]="formModel.get('categories').untouched||
            !formModel.hasError('categoriesLength','categories')" >请至少选择一个类型!</span>
        </div>
       

      </div>
      <!-- /.box-body -->
      <div class="box-footer">
        <button type="submit" class="btn btn-default">取消</button>
        <!-- 控制表单不合法时,保存按钮不可点击 -->
        <button type="submit" [disabled]="formModel.invalid" class="btn btn-info pull-right" (click)="save()" >保存</button>
      </div>
      <!-- /.box-footer -->
    </form>
  </div>
  <!-- /.box -->

页面效果分别为:

【1】股票列表


【2】股票修改



猜你喜欢

转载自blog.csdn.net/qq_21987433/article/details/80253314