Fab
Fab

Reputation: 954

Angular 2/4 Master Detail Patterns

I've been working with Angular for a few months now and started to notice a few patterns with master details where the details is some edit form.

Parent - Child Component Pattern If my details component is a child of the master component I can simple use an Input for the selected object and bind properties and hide show the different components, this pattern seems to work great

Parent - Modal Pattern same as above but usually use one component and just loading the row in a modal

Route Params Pattern If my details is not a child and I use the router, well this only accepts a string so I pass the id and find myself having to make an api call to get the selected object since the route params only support a string and not passing an object. This seems like a use case when maybe the parent doesn't contain all the properties the detail or the form needs.

Shared Service Pattern Using a Service to Share data between the 2 components

Any thoughts or any other patterns I'm missing?

Upvotes: 1

Views: 1078

Answers (1)

A. Tim
A. Tim

Reputation: 3206

Depending on your implementation, you can kinda "cache" your data in Service.

@Component({})
export class Component1{
    constructor(service: Service, router: Router){}

    onSomeAction(id){
        this.service.getEntityById(id);
    }

    redirectToDetails(id: number){
         this.router.navigate(["/details", id]);
    }
}

@Component({})
export class Component2() implements OnInit{

    public entity: Entity;

    constructor(service: Service, acivatedRoute: ActivatedRoute){}

    ngOnInit(){
        this.service.getEntityById(this.activatedRoute.getParams().get("id")).subscribe((entity) => {
            this.entity = entity;
        });
    }
}

@Injectable()
export class Service{

    public knownEntities: Map<number, Entity> = new Map<>();

    constructor(resource: Resource){
    }

    getNewEntityById(id: number): Observable<Entity>{
        return this.resource.getEntityFromBackendById().map((data) => {
            let entity: Entity = data.json();
            this.knownEntities.push(id, entity);
            return entity;
        });
    }

    getEntityById(id: number): Observable<Entity>{
        let knownEntity: Entity = this.knownEntities.get(id);
        if(knownEntity){
             return Observable.of(knownEntity);
        }else{
             return this.getNewEntityById(id);
        }
    }
}

Another approach - to have own RouterParameterService service which serves as global variable

@Inject()
export class RouterParameterService(){

    private _routerParam: any;

    public set routerParam(value: any){
        this._routerParam = value;
    }

    public get routerParam(): any{
        if(!this._routerParam){
            throw Error("No Router param set");
        }
        let tmp = this._routerParam;
        this._routerParam = null;
        return tmp;
    }
}

@Component({})
export class Component1(){

    constructor(service: RouterParameterService, router: Router){}

    navigateAction(){
        this.service.routerParam = {id: 1, fName: "A", lName = "Tim"};
        this.router.navigate("/details");
    }
}

@Component({})
export class Component2() implements OnInit{

    public entity: any;

    constructor(service: RouterParameterService){}

    ngOnInit(){
        this.entity = this.service.routerParam;
    }
}

Upvotes: 1

Related Questions