Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ <h5 class="mb-3">Categories</h5>
<!-- title -->
<h5 class="mb-3">Price</h5>

<form [formGroup]="formSearchByPrice">
<form [formGroup]="searchForm">
<input type="search" formControlName="priceFrom" placeholder="Price From"
class="form-control mb-2">
<input type="search" formControlName="priceTo" placeholder="Price To"
Expand All @@ -41,7 +41,7 @@ <h5 class="mb-3">Rating</h5>

<div class="form-check mb-2" *ngFor="let star_list of [].constructor(5); let i = index">
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

czy jest może jakiś ładniejszy sposób na to żeby wygenerować te gwiazdki?
wiem, że moglabym wrzucic tą 5 do zmiennej i byloby troche ladniej, ale chodzi mi o cos jeszcze bardziej poprawnego

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tak, można w ts zrobić np. tablicę obiektów, gdzie obiekt by miał dane potrzebne do prezentacji gwiazdki. Ciekawy sposób masz ale raczej tak nie robimy

<!-- input -->
<input class="form-check-input" type="checkbox" value="{{5-i}}">
<input class="form-check-input" type="checkbox" value="{{5-i}}" (change)="onCheckChange($event)">
<label class="form-check-label" for="{{5-i}}">

<i class="bi bi-star-fill text-warning" *ngFor="let star_ind of [].constructor(5-i)"></i>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { FormControl, FormGroup } from '@angular/forms';
import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms';
import { filter, map, startWith, switchMap, tap } from 'rxjs/operators';
import { CategoryModel } from '@app/models/category.model';
import { ProductsService } from '@app/services/products.service';
Expand Down Expand Up @@ -85,16 +85,17 @@ export class CategoryProductsComponent {


// SEARCH BY PRICE
readonly formSearchByPrice: FormGroup = new FormGroup({
readonly searchForm: FormGroup = new FormGroup({
priceFrom: new FormControl(),
priceTo: new FormControl(),
ratingsArray: new FormArray([]),
});

readonly productsByCategory$: Observable<ProductModel[]> = combineLatest([
this._productsService.getAll(),
this.category,
this.sortBy$,
this.formSearchByPrice.valueChanges.pipe(startWith({ priceFrom: -1, priceTo: 9999999 })),
this.searchForm.valueChanges.pipe(startWith({ priceFrom: -1 })),
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

czemu właściwie muszę podać cokolwiek w startWith? jesli usune tez i priceFrom to przestaje mi sie wyswietlac lista

to dlatego że w 94 linijce w category-products.components.ts mam combineLatest i musi się wygenerować jakakolwiek wartość dla searchForm, żeby dostarczyło wszystkie elementy do combineLatest i przeszło dalej?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dokładnie tak, bez tego dane załadowałyby się dopiero po zmianach w formularzu np. dodaniu priceFrom

]).pipe(
map(
([products, category, sortBy, searchValues]: [
Expand All @@ -104,13 +105,19 @@ export class CategoryProductsComponent {
SearchParamsQueryModel
]) => {

console.log(searchValues)

const filteredProducts = products.filter(
(product) => product.categoryId === category.id
).filter(
(product) =>
(!searchValues.priceFrom || product.price >= searchValues.priceFrom)
&&
(!searchValues.priceTo || product.price <= searchValues.priceTo)
&&
(!searchValues.ratingsArray ||
searchValues.ratingsArray.length === 0 ||
searchValues.ratingsArray.includes(Math.floor(product.ratingValue).toString()))
);


Expand Down Expand Up @@ -191,7 +198,6 @@ export class CategoryProductsComponent {
)
.pipe(
tap(([pageNumberOptions, form]) => {

return this._router.navigate([], {
queryParams: {
pageSize: form.pageSize,
Expand All @@ -202,5 +208,29 @@ export class CategoryProductsComponent {
)
.subscribe();

onCheckChange(event:Event) {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

czy jest może jakiś lepszy typ niż Event, tak żebym nie musiała póżniej zapisywać eventTarget jako HTMLInputElement?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

w zwykłym bootstrapowym checkbox chyba nie, tutaj ewentualnie dać typ 'any' zamiast Event, ale Twoje rozwiązanie na plus

W angular material jest event specjalny z którym jest dużo łatwiej

const formArray: FormArray = this.searchForm.get('ratingsArray') as FormArray;
const eventTarget = event.target as HTMLInputElement

/* Selected */
if(eventTarget.checked){
// Add a new control in the arrayForm
formArray.push(new FormControl(eventTarget.value));
}
/* unselected */
else{
// find the unselected element
let i: number = 0;

formArray.controls.forEach((ctrl: AbstractControl) => {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tutaj w przykładzie było żeby ctrl oznaczyc jako FormControl, ale nie działało i musiałam użyć AbstractControl

https://stackoverflow.com/questions/40927167/angular-reactiveforms-producing-an-array-of-checkbox-values

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Przykład który podałaś jest sprzed 6 lat, to dużo jak na programowanie xd

możesz nie robić tego na forEach tylko znaleźć index za pomocą metody findIndex na formArray.controls i po tym indeksie usunąć element.

Zmienna 'let i' jest tutaj niepotrzebna, metoda forEach jako drugi parametr ma index elementu np.
formArray.controls.forEach((ctr: AbstractControl, idx) => { ... })

Nie jestem pewien, ale FormControl rozszerza AbstractControl, i tym może to być spowodowane co do typu.

if(ctrl.value == eventTarget.value) {
// Remove the unselected element from the arrayForm
formArray.removeAt(i);
return;
}

i++;
});
}
}
}
1 change: 1 addition & 0 deletions src/app/query-models/search-params.query-model.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export interface SearchParamsQueryModel {
readonly priceFrom: number;
readonly priceTo: number;
readonly ratingsArray: string[];
}