7

I have one parent component with two child components (dataset-create and dataset-detail) in Angular2. The Parent component controls which of the two component is shown at any given time by using this code in its template:

<div [ngSwitch]="mode">
<template [ngSwitchWhen]="'create'">
    <dataset-create [dataset]="dataset" (close)="onDatasetFormClose()"></dataset-create>
</template>
<template [ngSwitchWhen]="'detail'">
    <dataset-detail [dataset]="dataset" (close)="onDatasetFormClose()"></dataset-detail>
</template>
</div>

The parent component listens for the event (close) from the children. When it receives it, a callback function is called (onDatasetFormClose()) which has the following code:

private onDatasetFormClose() {
    this.mode = "list";
}

This function changes the value of the mode variable. This causes both ngSwitchWhen statements to fail and thus the currently active child component gets destroyed.

Also, FYI, this is how the template of one of the child components looks like:

<form novalidate="novalidate">
    <button type="button" (click)="onClose()">close</button>
    <button type="submit" (click)="onSubmit()">submit</button>
    <label for="dataFileD">data</label>
    <input id="dataFileD" type="file" (change)="onFileChange($event)">
</form>

However, this solution looks "wrong" to me, because it relies on the parent component (thus making is harder to reuse it independently).

I guess another way to achieve a similar result would be to use a router. This solution not only sounds "too-bloated-for-no-reason", but also suffers from the same problem as my solution above: the child component can not be used independently.

Is it possible to have a child component remove itself from the DOM? What is the correct way to handle situations like this? Maybe having components removing themselves from the DOM is a bad Angular2 coding practice?

Thanks in advance.

AstrOne
  • 3,569
  • 7
  • 32
  • 54
  • 1
    I think it is fine for a component to require a parent component. Any component that emits an event probably requires a parent component. E.g., to implement tabs, you probably need a parent `tabset` component, in addition to the `tab` child components. – Mark Rajcok Jan 28 '16 at 21:22

2 Answers2

4

I think it is fine for a component to require a parent component. Components that emit an event usually require a parent component. And sometimes components are more tightly coupled, or are intended/required to be used together. E.g., to implement tabs, we probably need a parent tabset component, in addition to the tab child components. E.g., see the ng2-bootstrap tabs implmenentation.

Relying on a parent component(s) might also be a conscious design decision. For example, if we are modeling our application using immutable application data (see Savkin blog), we might purposely prevent our component from modifying any application data. If a delete operation is required, we may emit an event in order to have some higher level component modify the application data (and then send it back to us via an input property).

Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
  • Actually your points do make a lot of sense. I decided to follow that approach! Thanks! – AstrOne Jan 31 '16 at 23:04
  • Good to see others having this type of issue. I'm actually attempting to make a child send data to the parent (parent displays the data). At first I was using another service to hold the data, and both parent and child depended on that. It was truly annoying, what you have here solves that issue the way I feel it should be done. – Chris Feb 02 '16 at 17:04
  • @Chris, if the data you are sharing is contained in an array or an object (i.e., a reference type, rather than a primitive type (string, number, boolean)), then the parent can already see any changes you make to the shared data in the child, because the parent and child share the same reference. See [this answer](http://stackoverflow.com/a/34208500/215945) for more info. It may simplify what you are trying to accomplish. – Mark Rajcok Feb 02 '16 at 17:12
  • @MarkRajcok thanks for the tip! I actually think I did that by accident once, here though I'm trying to do more of a "a button was clicked in the child, let the parent know to show something". So it was very much an event, but I'll keep your hint in mind when I try to pull other shenanigans. – Chris Feb 04 '16 at 01:26
0

Why don't you have a bloolean flag say show on the sub component. Then just change it to false when you need to. In the template, just wrap everything with

Gordon Sun
  • 278
  • 1
  • 19