Angular 7 - 重用组件以显示过滤后的集合
Angular 7 - reuse component to display filtered collections
我正在尝试使用 MySQL 数据库开发基于 Angular7 的 Web 应用程序项目(提供送餐服务的在线餐厅)。应用程序正在使用路由器在站点上导航和加载组件。
首先,应用程序的重要(受影响)部分-routing.module:
app-routing.module.ts
[...]
{
path: 'menu',
component: MenuComponent,
children: [
{
path: '',
redirectTo: 'categories',
pathMatch: 'prefix'
},
{
path: 'categories',
component: ProductCategoriesComponent,
resolve: {
productCategories: CategoriesResolver,
products: ProductsResolve
},
},
{
path: 'categories/:id',
component: ProductsByCategoryComponent,
resolve: {
productsByCategory: ProductsResolveByCategory,
productCategories: CategoriesResolver
}
},
{
path: '**',
redirectTo: 'categories',
pathMatch: 'prefix'
}
],
},
[...]
**用例场景如下:
I. 用户在导航栏上点击 "Menu" navlink - 正在加载菜单组件:
url 动作后的路径:localhost:4200/menu/categories/ **
菜单-component.html
<router-outlet></router-outlet>
这只是加载菜单提供的产品类别的占位符 - Angular 将用户重定向到 menu/categories 并正在加载 ProductCategoriesComponent。这个使用两个解析器 - 实际解析所有产品类别和所有产品(由于没有选择特定类别,它们都被加载)。
类别ID如下:
1 - 开胃菜
2 - 披萨
3 - 意大利面
4 - 饮料
5 - 甜点
** 二。用户选择特定类别后,将过滤整个列表并在后端 returns 具有请求的类别 ID 的新对象列表:**
product.resolve.ts
@Injectable()
export class ProductsResolveByCategory implements Resolve<any> {
constructor(private productService: ProductService) {
}
resolve(route: ActivatedRouteSnapshot) {
return this.productService.getProductsByCategoryId(route.params['id']);
}
}
路由将我们引导至例如:localhost:4200/menu/categories/1 当已选择 "appetizers" 类别时。
到目前为止,应用程序运行良好,但出现了在特定条件下显示内容的问题 - 当用户在 /menu/categories/1 并且想要选择另一个类别(例如从 1 更改为 2 ),视图不会自行刷新 - 没有加载具有不同类别 ID 的产品,我们仍然可以看到旧的 - 目前的解决方法是再次单击菜单按钮,然后单击所需的类别。更重要的是,在浏览器中单击 "back"(因此它应该 return 到 menu/categories/)会抛出错误请求(错误 400),因为前端使用 /menu/categories/categories 发送请求(双倍!)而不是 'id'。我找不到任何合乎逻辑的解释,为什么 'id' 被 'categories' 词取代:
products.service.ts
public getProductsByCategoryId(id: number): Observable<Array<ProductModel>> {
return this.http.get('/api/products/categories/' + id).pipe(map((response: Array<ProductModel>) => {
this.productsByCategory = response;
return this.productsByCategory;
}));
}
产品-category.component.ts
Component({
selector: 'app-products-by-category',
templateUrl: './products-by-category.component.html',
styleUrls: ['./../products/products.component.css'],
})
export class ProductsByCategoryComponent implements OnInit {
private productsByCategory: Array<ProductModel> = [];
constructor(private productService: ProductService,
private route: ActivatedRoute) {
}
ngOnInit() {
if (this.route.snapshot.data['productsByCategory']) {
this.productsByCategory = this.route.snapshot.data['productsByCategory'];
}
}
}
所以总结起来,有两个(很可能是逻辑上的愚蠢错误)问题:
- 为什么从 menu/categories/1 更改为 menu/categories/2 时,没有加载正确的项目,
- 为什么当导航回 /menu/categories/ 时,前端发送 /menu/categories/categories/ 而不是 /menu/categories/ - 作为 'id' 变量,它发送 'categories' 字...(当用户从浏览器中的 link 末尾删除 /1 时也会发生此问题)
如有任何帮助,我们将不胜感激。谢谢!
要在您的组件中使用更新,您应该订阅数据,而不是通过快照访问它。使用 this.route.data.subscribe((data) => { this.productsByCategory = data['productsByCategory'];})
而不是 this.route.snapshot.data['productsByCategory']
。
要解决第二个问题,请从路由器配置中删除 path: ''
配置。我认为这就足够了,因为 path: '**'
配置已经处理了这种情况。
我正在尝试使用 MySQL 数据库开发基于 Angular7 的 Web 应用程序项目(提供送餐服务的在线餐厅)。应用程序正在使用路由器在站点上导航和加载组件。
首先,应用程序的重要(受影响)部分-routing.module:
app-routing.module.ts
[...]
{
path: 'menu',
component: MenuComponent,
children: [
{
path: '',
redirectTo: 'categories',
pathMatch: 'prefix'
},
{
path: 'categories',
component: ProductCategoriesComponent,
resolve: {
productCategories: CategoriesResolver,
products: ProductsResolve
},
},
{
path: 'categories/:id',
component: ProductsByCategoryComponent,
resolve: {
productsByCategory: ProductsResolveByCategory,
productCategories: CategoriesResolver
}
},
{
path: '**',
redirectTo: 'categories',
pathMatch: 'prefix'
}
],
},
[...]
**用例场景如下: I. 用户在导航栏上点击 "Menu" navlink - 正在加载菜单组件: url 动作后的路径:localhost:4200/menu/categories/ **
菜单-component.html
<router-outlet></router-outlet>
这只是加载菜单提供的产品类别的占位符 - Angular 将用户重定向到 menu/categories 并正在加载 ProductCategoriesComponent。这个使用两个解析器 - 实际解析所有产品类别和所有产品(由于没有选择特定类别,它们都被加载)。
类别ID如下: 1 - 开胃菜 2 - 披萨 3 - 意大利面 4 - 饮料 5 - 甜点
** 二。用户选择特定类别后,将过滤整个列表并在后端 returns 具有请求的类别 ID 的新对象列表:**
product.resolve.ts
@Injectable()
export class ProductsResolveByCategory implements Resolve<any> {
constructor(private productService: ProductService) {
}
resolve(route: ActivatedRouteSnapshot) {
return this.productService.getProductsByCategoryId(route.params['id']);
}
}
路由将我们引导至例如:localhost:4200/menu/categories/1 当已选择 "appetizers" 类别时。
到目前为止,应用程序运行良好,但出现了在特定条件下显示内容的问题 - 当用户在 /menu/categories/1 并且想要选择另一个类别(例如从 1 更改为 2 ),视图不会自行刷新 - 没有加载具有不同类别 ID 的产品,我们仍然可以看到旧的 - 目前的解决方法是再次单击菜单按钮,然后单击所需的类别。更重要的是,在浏览器中单击 "back"(因此它应该 return 到 menu/categories/)会抛出错误请求(错误 400),因为前端使用 /menu/categories/categories 发送请求(双倍!)而不是 'id'。我找不到任何合乎逻辑的解释,为什么 'id' 被 'categories' 词取代:
products.service.ts
public getProductsByCategoryId(id: number): Observable<Array<ProductModel>> {
return this.http.get('/api/products/categories/' + id).pipe(map((response: Array<ProductModel>) => {
this.productsByCategory = response;
return this.productsByCategory;
}));
}
产品-category.component.ts
Component({
selector: 'app-products-by-category',
templateUrl: './products-by-category.component.html',
styleUrls: ['./../products/products.component.css'],
})
export class ProductsByCategoryComponent implements OnInit {
private productsByCategory: Array<ProductModel> = [];
constructor(private productService: ProductService,
private route: ActivatedRoute) {
}
ngOnInit() {
if (this.route.snapshot.data['productsByCategory']) {
this.productsByCategory = this.route.snapshot.data['productsByCategory'];
}
}
}
所以总结起来,有两个(很可能是逻辑上的愚蠢错误)问题:
- 为什么从 menu/categories/1 更改为 menu/categories/2 时,没有加载正确的项目,
- 为什么当导航回 /menu/categories/ 时,前端发送 /menu/categories/categories/ 而不是 /menu/categories/ - 作为 'id' 变量,它发送 'categories' 字...(当用户从浏览器中的 link 末尾删除 /1 时也会发生此问题)
如有任何帮助,我们将不胜感激。谢谢!
要在您的组件中使用更新,您应该订阅数据,而不是通过快照访问它。使用 this.route.data.subscribe((data) => { this.productsByCategory = data['productsByCategory'];})
而不是 this.route.snapshot.data['productsByCategory']
。
要解决第二个问题,请从路由器配置中删除 path: ''
配置。我认为这就足够了,因为 path: '**'
配置已经处理了这种情况。