Angular 2 具有反应式表单的多类别复选框过滤器
Angular 2 Multiple Category Checkbox Filter With Reactive Form
我正在尝试使用 2 个不同的类别(希望更多)做一个更复杂的(对我来说)过滤器,frameBrand 和 frameColor。我想过滤到特定品牌,然后使用这些结果过滤颜色,直到我有更多 specific/narrow 搜索。我正在努力筛选 2 个类别
在下面的示例 JSON 中,我想单击品牌复选框以获取“anne klein”镜框,然后单击颜色复选框“棕色”以查看“anne klein - brown”镜框。 2 个复选框,每个复选框来自不同的“类别”。理想情况下,我可以将其扩展为使用其他类别,例如价格复选框。我已经使用 Whosebug 通过 .filter 获得了我所处的位置,但是使用 Angular.
的多个类别和复选框并没有看到太多
{
"frames": [
{
"frameBrand": "altair",
"frameColor": "Black",
"frameId": 1,
"frameName": "A5052",
"releaseDate": "05-01-2021",
"framePrice": 25,
"frameDescription": "this is an altair frame.",
"imageUrl": "/assets/images/frames/ALO/A5052/A5052_001_LG_01.jpg",
"categories": [1]
},
{
"frameBrand": "anne klein",
"frameColor": "Ruby",
"frameId": 2,
"frameName": "AK5091",
"releaseDate": "05-01-2021",
"framePrice": 45,
"frameDescription": "this is an anne klein frame.",
"imageUrl": "/assets/images/frames/AKO/AK5091/AK5091_610_LG_01.jpg",
"categories": [2]
},
{
"frameBrand": "anne klein",
"frameColor": "Brown",
"frameId": 3,
"frameName": "AK5090",
"releaseDate": "05-01-2021",
"framePrice": 45,
"frameDescription": "this is an anne klein frame.",
"imageUrl": "/assets/images/frames/AKO/AK5090/AK5090_200_LG_01.jpg",
"categories": [2]
},
{
"frameBrand": "bebe",
"frameColor": "Silver",
"frameId": 4,
"frameName": "BB5192",
"releaseDate": "05-01-2021",
"framePrice": 40,
"frameDescription": "this is an bebe frame.",
"imageUrl": "/assets/images/frames/BBO/BB5192/BB5192_001_LG_01.jpg",
"categories": [3]
}
]
}
在我的 TS 文件中,我有 3 个函数,filterFramesByBrand、filterFramesByColor 和 filterResults。当 (change)="filterFramesByBrand($event)" 发生时,我从品牌和颜色中取出选中的复选框并将它们推送到我的 formGroup 中的不同数组。然后我 运行 filterResults 函数,我试图让魔法发生。我已经按预期过滤了品牌,但混合使用这两个类别(品牌和颜色)让我感到困惑。我已经注释掉了我的 filterResults 函数的颜色部分,因为出于某种原因它不像品牌部分那样工作。
checkboxForm: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.checkboxForm = this.fb.group({
brandCheckArray: this.fb.array([]),
colorCheckArray: this.fb.array([])
});
}
filteredFrames: IFrames[] = [...this.frames];
filterFramesByBrand(category) {
const brandCheckArray: FormArray = this.checkboxForm.get(
"brandCheckArray"
) as FormArray;
if (category.target.checked) {
brandCheckArray.push(new FormControl(category.target.value));
} else {
let i: number = 0;
brandCheckArray.controls.forEach((item: FormControl) => {
if (item.value == category.target.value) {
brandCheckArray.removeAt(i);
return;
}
i++;
});
}
this.filterResults();
}
filterFramesByColor(category) {
const colorCheckArray: FormArray = this.checkboxForm.get(
"colorCheckArray"
) as FormArray;
if (category.target.checked) {
colorCheckArray.push(new FormControl(category.target.value));
} else {
let i: number = 0;
colorCheckArray.controls.forEach((item: FormControl) => {
if (item.value == category.target.value) {
colorCheckArray.removeAt(i);
return;
}
i++;
});
}
this.filterResults();
}
filterResults() {
this.filteredFrames = this.frames.filter(el => {
let frameBrandEl = el.frameBrand
.split(" ")
.join("")
.toLowerCase();
// let frameColorsEl = el.frameColor
// .split(" ")
// .join("")
// .toLowerCase();
let brandsChecked = this.checkboxForm.get("brandCheckArray").value;
// let colorsChecked = this.checkboxForm.get("colorCheckArray").value;
var fixCheckedBrands = brandsChecked.map(v =>
v
.split(" ")
.join("")
.toLowerCase()
);
// var fixCheckedColors = colorsChecked.map(v =>
// v
// .split(" ")
// .join("")
// .toLowerCase()
// );
console.log(frameBrandEl);
// console.log(frameColorsEl);
console.log(fixCheckedBrands);
// console.log(fixCheckedColors);
return frameBrandEl.includes(fixCheckedBrands);
// return frameColorsEl.includes(fixCheckedColors);
});
// if there are no checked checkboxes - show all
if (this.checkboxForm.value.brandCheckArray.length === 0) {
this.filteredFrames = this.frames;
}
}
最后:这是我的 StackBlitz 的 link - https://stackblitz.com/edit/angular-ivy-product-filters?file=src%2Fapp%2Fproduct-filter.ts 我认为通过一些关于 .filter 函数的指导我可以解决这个问题。感谢您的帮助或建议。
我会简化你的逻辑。
与其使用 FormArrays
的 FormGroup
执行此操作(除非这不是要求),这里最好的方法是创建 FilterComponent
接受作为输入示例对象
type CheckboxFilter = { name: string, isChecked: boolean }
。如果需要,您可能可以添加 id
。
创建后将 Output
添加到您的 FilterComponent
。
现在您添加到 BrandChanged
和 ColorChanged
的处理程序。基于此,您可以存储选定的滤镜并将它们应用到您的相框上。
这甚至可以让您使其更具反应性。
你可以为 Brand
和 Color
贴上 BehaviourSubject<string[]>
,一旦发生事件你就可以操纵主题。
稍后只有 combainLatest
来自 JSON 文件或 API 的帧,然后像这样应用:
combineLatest([frames$, brands$, colors$]).pipe(filter([frames, brands, colors]) => ...)
这里正在工作stackblitz
我正在尝试使用 2 个不同的类别(希望更多)做一个更复杂的(对我来说)过滤器,frameBrand 和 frameColor。我想过滤到特定品牌,然后使用这些结果过滤颜色,直到我有更多 specific/narrow 搜索。我正在努力筛选 2 个类别
在下面的示例 JSON 中,我想单击品牌复选框以获取“anne klein”镜框,然后单击颜色复选框“棕色”以查看“anne klein - brown”镜框。 2 个复选框,每个复选框来自不同的“类别”。理想情况下,我可以将其扩展为使用其他类别,例如价格复选框。我已经使用 Whosebug 通过 .filter 获得了我所处的位置,但是使用 Angular.
的多个类别和复选框并没有看到太多{
"frames": [
{
"frameBrand": "altair",
"frameColor": "Black",
"frameId": 1,
"frameName": "A5052",
"releaseDate": "05-01-2021",
"framePrice": 25,
"frameDescription": "this is an altair frame.",
"imageUrl": "/assets/images/frames/ALO/A5052/A5052_001_LG_01.jpg",
"categories": [1]
},
{
"frameBrand": "anne klein",
"frameColor": "Ruby",
"frameId": 2,
"frameName": "AK5091",
"releaseDate": "05-01-2021",
"framePrice": 45,
"frameDescription": "this is an anne klein frame.",
"imageUrl": "/assets/images/frames/AKO/AK5091/AK5091_610_LG_01.jpg",
"categories": [2]
},
{
"frameBrand": "anne klein",
"frameColor": "Brown",
"frameId": 3,
"frameName": "AK5090",
"releaseDate": "05-01-2021",
"framePrice": 45,
"frameDescription": "this is an anne klein frame.",
"imageUrl": "/assets/images/frames/AKO/AK5090/AK5090_200_LG_01.jpg",
"categories": [2]
},
{
"frameBrand": "bebe",
"frameColor": "Silver",
"frameId": 4,
"frameName": "BB5192",
"releaseDate": "05-01-2021",
"framePrice": 40,
"frameDescription": "this is an bebe frame.",
"imageUrl": "/assets/images/frames/BBO/BB5192/BB5192_001_LG_01.jpg",
"categories": [3]
}
]
}
在我的 TS 文件中,我有 3 个函数,filterFramesByBrand、filterFramesByColor 和 filterResults。当 (change)="filterFramesByBrand($event)" 发生时,我从品牌和颜色中取出选中的复选框并将它们推送到我的 formGroup 中的不同数组。然后我 运行 filterResults 函数,我试图让魔法发生。我已经按预期过滤了品牌,但混合使用这两个类别(品牌和颜色)让我感到困惑。我已经注释掉了我的 filterResults 函数的颜色部分,因为出于某种原因它不像品牌部分那样工作。
checkboxForm: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.checkboxForm = this.fb.group({
brandCheckArray: this.fb.array([]),
colorCheckArray: this.fb.array([])
});
}
filteredFrames: IFrames[] = [...this.frames];
filterFramesByBrand(category) {
const brandCheckArray: FormArray = this.checkboxForm.get(
"brandCheckArray"
) as FormArray;
if (category.target.checked) {
brandCheckArray.push(new FormControl(category.target.value));
} else {
let i: number = 0;
brandCheckArray.controls.forEach((item: FormControl) => {
if (item.value == category.target.value) {
brandCheckArray.removeAt(i);
return;
}
i++;
});
}
this.filterResults();
}
filterFramesByColor(category) {
const colorCheckArray: FormArray = this.checkboxForm.get(
"colorCheckArray"
) as FormArray;
if (category.target.checked) {
colorCheckArray.push(new FormControl(category.target.value));
} else {
let i: number = 0;
colorCheckArray.controls.forEach((item: FormControl) => {
if (item.value == category.target.value) {
colorCheckArray.removeAt(i);
return;
}
i++;
});
}
this.filterResults();
}
filterResults() {
this.filteredFrames = this.frames.filter(el => {
let frameBrandEl = el.frameBrand
.split(" ")
.join("")
.toLowerCase();
// let frameColorsEl = el.frameColor
// .split(" ")
// .join("")
// .toLowerCase();
let brandsChecked = this.checkboxForm.get("brandCheckArray").value;
// let colorsChecked = this.checkboxForm.get("colorCheckArray").value;
var fixCheckedBrands = brandsChecked.map(v =>
v
.split(" ")
.join("")
.toLowerCase()
);
// var fixCheckedColors = colorsChecked.map(v =>
// v
// .split(" ")
// .join("")
// .toLowerCase()
// );
console.log(frameBrandEl);
// console.log(frameColorsEl);
console.log(fixCheckedBrands);
// console.log(fixCheckedColors);
return frameBrandEl.includes(fixCheckedBrands);
// return frameColorsEl.includes(fixCheckedColors);
});
// if there are no checked checkboxes - show all
if (this.checkboxForm.value.brandCheckArray.length === 0) {
this.filteredFrames = this.frames;
}
}
最后:这是我的 StackBlitz 的 link - https://stackblitz.com/edit/angular-ivy-product-filters?file=src%2Fapp%2Fproduct-filter.ts 我认为通过一些关于 .filter 函数的指导我可以解决这个问题。感谢您的帮助或建议。
我会简化你的逻辑。
与其使用 FormArrays
的 FormGroup
执行此操作(除非这不是要求),这里最好的方法是创建 FilterComponent
接受作为输入示例对象
type CheckboxFilter = { name: string, isChecked: boolean }
。如果需要,您可能可以添加 id
。
创建后将 Output
添加到您的 FilterComponent
。
现在您添加到 BrandChanged
和 ColorChanged
的处理程序。基于此,您可以存储选定的滤镜并将它们应用到您的相框上。
这甚至可以让您使其更具反应性。
你可以为 Brand
和 Color
贴上 BehaviourSubject<string[]>
,一旦发生事件你就可以操纵主题。
稍后只有 combainLatest
来自 JSON 文件或 API 的帧,然后像这样应用:
combineLatest([frames$, brands$, colors$]).pipe(filter([frames, brands, colors]) => ...)
这里正在工作stackblitz