1

I'm creating a component that I'd like to use as a child in another component but also as a standalone view.

For instance, component ViewCarsComponent pairs a list, SmallCarsListComponent, and a panel for viewing detailed information about a Car object, CarDetailComponent. When an item from the list is selected, the Car object for that item is provided to the details panel via an @Input and the panel is updated. However, when I navigate to /cars/small/20, I want to show the detail panel by itself with the details for the Car with ID 20. This one component can thus take a Car object, provided by the sibling list component via @Input, or a number as a URL parameter that it can then use to make its own query.

Is there a better way of doing this? Is there some middleware that I should be writing that can retrieve the Car corresponding to the ID provided as a URL parameter, then hand that off to CarDetailComponent, so said component never needs to make the request for the Car object itself? Should two separate components, one designed for @Input and one designed for URL parameters be made?

Zulfe
  • 820
  • 7
  • 25
  • I would be interested in a "best practice solution".... My thoughts, hope they help:I would probably remove input, create the route and add in place of as a child and have the component load the data (9/10 times you want small requests made to the back-end for data, also it keeps data out of the parent where it's not needed). options?; service layer could run both options, but ..you'd just be skinning the horse a different way. (s-layer holding id, or data, no need to pass param to component. but would depend on a parent at some level to fill the data. – Don Thomas Boyle Jan 24 '20 at 16:51

1 Answers1

1

Is there some middleware that I should be writing that can retrieve the Car corresponding to the ID provided as a URL parameter, then hand that off to CarDetailComponent, so said component never needs to make the request for the Car object itself?

I believe what you're looking for is a route-resolver. Upon routing a resolver can intercept a URL parameter, use it to fetch an object, and make it available to all components that render under that route. For example...

app-routing.module.ts

{
    path: 'widgets',
    component: WidgetsComponent,
},
{
    path: 'widgets/:id',
    resolve: { widget: WidgetResolver },
    children: [
        { path: '', redirectTo: 'details', pathMatch: 'prefix' },
        {
            path: 'details',
            component: WidgetDetailsComponent,
        },
        { path: 'edit', component: WidgetFormComponent }
    ]
},

widget.resolver.ts

@Injectable()
export class WidgetResolver implements Resolve<Widget> {
    constructor(private service: WidgetService) { }

    resolve(route: ActivatedRouteSnapshot): Observable<any> {
        return this.service.getById(parseInt(route.paramMap.get('id') || ''))
            .pipe(first()); // must complete to resolve route
    }
}

widget-details.component.ts

@Component({
    selector: 'app-widget-details',
    templateUrl: './widget-details.component.html',
    styleUrls: ['./widget-details.component.scss'],
})
export class WidgetDetailsComponent {
    widget$ = this.route.data.pipe(
        pluck('widget')
    );

    constructor(
        private route: ActivatedRoute
    ) { }
}
Adam Dunkerley
  • 664
  • 6
  • 14