使用异步管道的可观察字符串数组不更新 nouislider.on 事件内的视图
Observable string array using async pipe not updating view inside nouislider.on event
I am trying to implement noUiSlider in my search component.
我有 asyncCars: Observable<String[]>;
,其中包含过滤后的结果并使用 async
管道显示在 ngOnInit()
上。
我有一个 this.noUiSlider.on('end', this.myLogSliderEnd);
事件在释放滑块手柄时调用。可观察数组已更新但不更新视图。
任何人都可以帮助解决这个问题吗?下面我已经显示了问题所在的代码。
component.html
<ng-container *ngFor="let car of asyncCars | carFilter: queryString | async | paginate: { id: 'server', itemsPerPage: 50, currentPage: p, totalItems: total }">
</ng-container>
component.ts
declare var asyncCars: Observable<String[]>;
declare var carsResult: any;
interface IServerResponse {
items: string[];
total: number;
}
@Component({
moduleId: module.id,
selector: 'list-carsExample2',
templateUrl: '/AngularCarSearch/src/app/cars/CarSearchDisableFilterExample.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CarSearchDisableFilterExample {
cars = [];
filterArr = [];
asyncCars: Observable<String[]>;
p: number = 1;
total: number;
loading: boolean;
noUiSlider: any;
@ViewChild('priceSlider') priceSlider;
public ngOnInit(): void {
this.cars = carsResult;
this.getPage(1);
this.noUiSlider = this.buildSlider([this.minimumPrice, this.maximumPrice], this.priceSlider, priceDropdownValues, [this.sliderMin, this.sliderMax], '£{0}', false);
this.updateSlideLimits()
}
updateSlideLimits() {
this.noUiSlider.on('end', this.myLogSliderEnd);
}
public myLogSliderEnd = (values: any[], handle) => {
//Add the two values set on the slider to filterArray
this.filterArr = AddPriceToFilter([values[0], values[1]], false, this.filterArr);
//Do the search based on what is in filter array
this.cars = multiFilterSearch(carsResult, this.filterArr);
this.getPage(1);
}
getPage(page: number) {
this.loading = true;
this.asyncCars = serverCall(this.cars, page)
.do(res => {
this.total = res.total;
this.p = page;
this.loading = false;
})
.map(res => res.items);
}
}
/**
* Simulate an async HTTP call with a delayed observable.
*/
function serverCall(cars, page: number): Observable<IServerResponse> {
const perPage = 50;
const start = (page - 1) * perPage;
const end = start + perPage;
var ob = Observable
.of({
items: cars.slice(start, end),
total: cars.length
}).delay(100);
return ob
}
/**
* Filters an array of objects with multiple criteria.
*
* @param {Array} array: the array to filter
* @param {Object} filters: an object with the filter criteria as the property names
* @return {Array}
*/
function multiFilterSearch(array, filters) {
const filterKeys = Object.keys(filters);
// filters all elements passing the criteria
return array.filter((item) => {
// dynamically validate all filter criteria
return filterKeys.every(key => {
// ignores an empty filter
if (!filters[key].length) {
return true;
}
else if (key === "Price") {
return (item.PriceRetail >= filters["Price"][0] && item.PriceRetail <= filters["Price"][1])
}
else {
return filters[key].includes(item[key]);
}
});
});
}
function AddPriceToFilter(event, checked, filterArr) {
if (checked === false) {
if (event[0] === 'Any' && event[1] === 'Any') {
}
else {
filterArr["Price"] = [event[0], event[1]];
}
}
return filterArr;
}
我预计视图会更新,因为 asyncCars 可观察值已更改,但这并未反映在视图上?
您正在为 getPage
中的 asyncCars
分配一个新的 Observable。那就是问题所在。您可能想要做的是向已经存在的流添加一个值。使用 Subject
来实现这一点。
asyncCars = new Subject<String[]>();
getPage(page: number) {
this.loading = true;
serverCall(this.cars, page)
.do(res => {
this.total = res.total;
this.p = page;
this.loading = false;
})
.map(res => res.items)
.subscribe(
cars => this.asyncCars.next(cars)
);
}
I am trying to implement noUiSlider in my search component.
我有 asyncCars: Observable<String[]>;
,其中包含过滤后的结果并使用 async
管道显示在 ngOnInit()
上。
我有一个 this.noUiSlider.on('end', this.myLogSliderEnd);
事件在释放滑块手柄时调用。可观察数组已更新但不更新视图。
任何人都可以帮助解决这个问题吗?下面我已经显示了问题所在的代码。
component.html
<ng-container *ngFor="let car of asyncCars | carFilter: queryString | async | paginate: { id: 'server', itemsPerPage: 50, currentPage: p, totalItems: total }">
</ng-container>
component.ts
declare var asyncCars: Observable<String[]>;
declare var carsResult: any;
interface IServerResponse {
items: string[];
total: number;
}
@Component({
moduleId: module.id,
selector: 'list-carsExample2',
templateUrl: '/AngularCarSearch/src/app/cars/CarSearchDisableFilterExample.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CarSearchDisableFilterExample {
cars = [];
filterArr = [];
asyncCars: Observable<String[]>;
p: number = 1;
total: number;
loading: boolean;
noUiSlider: any;
@ViewChild('priceSlider') priceSlider;
public ngOnInit(): void {
this.cars = carsResult;
this.getPage(1);
this.noUiSlider = this.buildSlider([this.minimumPrice, this.maximumPrice], this.priceSlider, priceDropdownValues, [this.sliderMin, this.sliderMax], '£{0}', false);
this.updateSlideLimits()
}
updateSlideLimits() {
this.noUiSlider.on('end', this.myLogSliderEnd);
}
public myLogSliderEnd = (values: any[], handle) => {
//Add the two values set on the slider to filterArray
this.filterArr = AddPriceToFilter([values[0], values[1]], false, this.filterArr);
//Do the search based on what is in filter array
this.cars = multiFilterSearch(carsResult, this.filterArr);
this.getPage(1);
}
getPage(page: number) {
this.loading = true;
this.asyncCars = serverCall(this.cars, page)
.do(res => {
this.total = res.total;
this.p = page;
this.loading = false;
})
.map(res => res.items);
}
}
/**
* Simulate an async HTTP call with a delayed observable.
*/
function serverCall(cars, page: number): Observable<IServerResponse> {
const perPage = 50;
const start = (page - 1) * perPage;
const end = start + perPage;
var ob = Observable
.of({
items: cars.slice(start, end),
total: cars.length
}).delay(100);
return ob
}
/**
* Filters an array of objects with multiple criteria.
*
* @param {Array} array: the array to filter
* @param {Object} filters: an object with the filter criteria as the property names
* @return {Array}
*/
function multiFilterSearch(array, filters) {
const filterKeys = Object.keys(filters);
// filters all elements passing the criteria
return array.filter((item) => {
// dynamically validate all filter criteria
return filterKeys.every(key => {
// ignores an empty filter
if (!filters[key].length) {
return true;
}
else if (key === "Price") {
return (item.PriceRetail >= filters["Price"][0] && item.PriceRetail <= filters["Price"][1])
}
else {
return filters[key].includes(item[key]);
}
});
});
}
function AddPriceToFilter(event, checked, filterArr) {
if (checked === false) {
if (event[0] === 'Any' && event[1] === 'Any') {
}
else {
filterArr["Price"] = [event[0], event[1]];
}
}
return filterArr;
}
我预计视图会更新,因为 asyncCars 可观察值已更改,但这并未反映在视图上?
您正在为 getPage
中的 asyncCars
分配一个新的 Observable。那就是问题所在。您可能想要做的是向已经存在的流添加一个值。使用 Subject
来实现这一点。
asyncCars = new Subject<String[]>();
getPage(page: number) {
this.loading = true;
serverCall(this.cars, page)
.do(res => {
this.total = res.total;
this.p = page;
this.loading = false;
})
.map(res => res.items)
.subscribe(
cars => this.asyncCars.next(cars)
);
}