在Angular2 API中调用不在视图中加载

时间:2016-10-21 18:31:27

标签: angular typescript rxjs

这里有新的网络开发人员(所以我提前为有些草率的代码道歉)。我被要求在Angular2中创建一个原型库存页面。

正如您在下面的代码中看到的那样。从EXAMPLEapi.service页面开始,我们将调用我们的基本后端API(' https://api.EXAMPLE.com/api/v1/inventory?'),然后将其传递给EXAMPLEapi.component上的ngOnInit在页面上加载我们的初始库存。

从这里,您应该能够选择各种过滤值(最小/最大年数,米拉色,颜色等)。这些值从表单(EXAMPLEapi.component.html)传递到refreshInv()函数(EXAMPLEapi.component),该函数在最终传递回API调用之前使用URLSearchParams将值转换为参数。

API的构建方式只需添加' min_price ='在基本URL的末尾应相应地反映库存调用。

问题是:当onSubmit通过过滤值时,我成功获得了200网络呼叫成功。不幸的是,没有任何库存加载到页面上。它只是空白。

EXAMPLEAPI.service.ts

import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';


@Injectable()
export class EXAMPLEAPIService {
constructor(public http: Http){}

baseUrl = "https://api.EXAMPLE.com/api/v1/inventory?";


getVehicles(params) {
    return this.http.get(this.baseUrl, params)
        .map(res => res.json());
}

click(): Observable<Data[]> {
    console.log(value);
}

log(x) {
    console.log(x);
}

EXAMPLE.component.ts

import {Component, OnInit} from 'angular2/core';
import {Http, RequestOptions, URLSearchParams, HTTP_PROVIDERS}       from 'angular2/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import {EXAMPLEService} from './EXAMPLEapi.service';
import {FormsModule} from 'angular2/forms';


@Component({
selector: 'example-container',
styles: [`
        * {
            display: inline-block;
            max-width: 500px;
            vertical-align: top;
        }
        .invbar {
            border: 1px solid black;
            padding: 5px;
            background-color: #6A7372;
            border-radius: 15px;
        }
        .hotel_container{
            border: 1px solid black;
            background-color: #6A7372;
            max-height: 410px;
        }
        #colorsBox{
            display: block;
        }
        input[type="checkbox"]{
            margin-left: 5px;
        }
        label{
            margin-top: 5px;
            color: #FF3B37;
        }
     `],
templateUrl: 'app/exampleapi.component.html',
providers: [HTTP_PROVIDERS, EXAMPLEAPIService]
})

export class EXAMPLEAPIComponent implements OnInit {
constructor(public EXAMPLEAPIService: EXAMPLEAPIService){


    this.minPrice = {
        value: ''
    };
    this.maxPrice = {
        value: ''
    };
    this.minYear = {
        value: '2013'
    };
    this.maxYear = {
        value: ''
    };

}

// On Page-Load this loads the API Call
ngOnInit() {
    this.EXAMPLEService.getVehicles()
        .subscribe(data => {
            this.vehicles = data.data;
            console.log(data.data[0].name);
        }
}

// Takes the Filter Parameters and passes them back into the API Call
refreshInv() {
    let params = new URLSearchParams();
    params.set('min_price', this.minPrice.value);
    params.set('max_price', this.maxPrice.value);
    params.set('min_year', this.minYear.value);
    params.set('max_year', this.maxYear.value);
    params.set('ext_color', this.colorsChecked);

    let options = new RequestOptions({
        search: params
    });
    console.log(options);
    return this.EXAMPLEService.getVehicles(options)
        .subscribe(data => this.vehicles = data.data);
}

// Keeps the Filter Queries Actively Refreshing on each interaction
onSubmit(value: any): Observable<Data[]> {
    console.log(value);
    return this.refreshInv()
};

// Dynamic Checkbox Generation for Color Filters
colors = ['Red', 'Blue', 'Yellow', 'Green', 'White', 'Black'];
colorsMap = {
    Red: false,
    Blue: false,
    Yellow: false,
};
colorsChecked = [];

initColorsMap() {
    for (var x=0; x<this.colors.length; x++) {
        this.colorsMap[this.colors[x]] = true;
    }
}

updateCheckedColors(color, event) {
    this.colorsMap[color] = event.target.checked;
}

colorUpdate() {
    for(var x in this.colorsMap) {
        if(this.colorsMap[x]) {
            this.colorsChecked.push[x];
        }
    }
    this.colors = this.colorsChecked;
    this.colorsChecked = [];
}

// Dynamic Checkbox Generation for Lift Filters
lifts = ['Lifted', 'Unlifted'];
liftsMap = {
    Lifted: false,
    Unlifted: false,
};
liftsChecked = [];

initLiftsMap() {
    for (var x=0; x<this.lifts.length; x++) {
        this.liftsMap[this.maps[x]] = true;
    }
}

updateCheckedMaps(map, event) {
    this.liftsMap[lift] = event.target.checked;
}

liftUpdate() {
    for(var x in this.liftMap) {
        if(this.liftMap[x]) {
            this.liftsChecked.push[x];
        }
    }
    this.lifts = this.liftsChecked;
    this.liftsChecked = [];
}

// Dynamic Checkbox Generation for Transmission Filters
trans = ['Manual', 'Automatic'];
transMap = {
    Manual: false,
    Automatic: false,
};
transChecked = [];

initTransMap() {
    for (var x=0; x<this.trans.length; x++) {
        this.transMap[this.trans[x]] = true;
    }
}

updateCheckedmap(map, event) {
    this.transMap[map] = event.target.checked;
}

transUpdate() {
    for(var x in this.transMap) {
        if(this.transMap[x]) {
            this.transChecked.push[x];
        }
    }
    this.trans = this.transChecked;
    this.transChecked = [];
}

// Dynamic Checkbox Generation for Interior Filters
ints = ['Cloth', 'Leather', 'Vinyl'];
intsMap = {
    Cloth: false,
    Leather: false,
    Vinyl: false,
};
intsChecked = [];

initIntMap() {
    for (var x=0; x<this.ints.length; x++) {
        this.intsMap[this.ints[x]] = true;
    }
}

updateCheckedmap(map, event) {
    this.intsMap[map] = event.target.checked;
}

intsUpdate() {
    for(var x in this.intsMap) {
        if(this.intsMap[x]) {
            this.intsChecked.push[x];
        }
    }
    this.ints = this.intsChecked;
    this.intsChecked = [];
}


}

1 个答案:

答案 0 :(得分:0)

首先,如果你想要一个如何设置angular2 plnkr(使用unpkg)的示例,look here

至于您的代码,您的refreshInv会返回订阅(Observable.subscribe()返回订阅),该订阅没有用,只能取消订阅。

我想建议一种不同的方法,对我来说很有效,并且会简化你的代码。实际上你的数据流是什么:&#39;查询&#39; - &GT; &#39;请求&#39; - &GT; &#39;显示&#39 ;.在rxjs中,这很容易编码为:

let items$ = jsonParams$
  .map(urlParamsMapper)
  .switchMap(urlParams => http.get(baseUrl, urlParams)
  .map(response => response.json().data);

urlParamsMapper获取基于json的查询(如您所指定)并将其转换为URLSearchParams

jsonParams$是一个可观察的(在我们的案例中是一个主题),您可以使用相关的查询详细信息进行更新:

let jsonParams$: Subject<any> = new BehaviorSubject({
  min_price: '',
  max_price: '',
  ...
  ext_color: ''
});

每次更新params时,都会构建新的json(代码中有逻辑),然后执行:

jsonParams$.next(currentParams);
在rxjs 4中

注意,您应该使用onNext而不是next

这将为您触发整个链条。

将其绑定到模板的最后一步是:

<my-item-renderer *ngFor="let item; of items$ | async;" [item]="item"></my-item>

注意 async,可让您绑定到观察者。

既然你可能想要保留你的服务架构,即在服务中保留http调用,你可能想要这样打破它:

在服务中:

createItemsLoader(jsonParams$: Observable<any>): Observable<Array<any>> {
  return jsonParams$.map(urlParamsMapper)
    .switchMap(urlParams => http.get(baseUrl, urlParams))
    .map(response => response.json().data);
}

然后在你的组件中:

let jsonParams$: Subject<any> = new BehaviorSubject({min_price: '' ...});
let items$ = ItemsService.createItemsLoader(jsonParams$);

refreshInv() {
  .... let jsonParams: any = construct json params ....
  this.jsonParams$.next(jsonParams);
}

这就是反应性编程的美妙之处,如果你正确地构建管道,你所要做的就是在正确的管道上发送新数据,而另一端正在收听的人将获得它。您上面的代码仍处于程序性思维中。