0

My team and I are currently making a component library using Angular (v8.x). We want to establish some house keeping rules and keep our component interfaces intuitive (ie. consistent naming of inputs and usage of patterns).

We have found between us two schools of thoughts around using @Inputs and nesting components.

Our delema can be described using the following (watered down) examples

Example component 1:

<our-component [hideChild]="childHidden"></our-component>

Example component 2:

<our-component>
  <our-child-component></our-child-component>
</our-component>

In example 1, the component has an @Input which shows and hides the child component hard coded in the template.

In example 2, the component is added (or not) as a child (via ngContent).

I am trying to find an assertation which dictates when to use one pattern over the other. I understand there may not be one. My current thinking is that if your component has n number of children, or n numbers of types of children, use component nesting. If the component will only ever have a single type of child use an input, and include your child component inside your parent components template.

I've checked the angular style guide, but can't find anything specific to this problem.

Does anyone know of any resources or has had experience making this distinction? I'd like to hear how and why you implemented it one way or the other.


Edit: Specifically, I would like endings to the following statements:

"Use @Inputs over nested components when ..." and "Use nested components over @Inputs when ..."


Edit 2: Appreciate I may not be expressing myself properly. With our component library, among other components, we are wrapping existing angular material components such as mat-input. We have a component that wraps the mat-form-field, mat-hint and mat-input components in our template. Our component looks like this:

<our-input
 [hideAssistiveText]="hideAssistiveText"
 [type]="inputType"
 [hint]="hint"
 [label]="label"
 [control]="control"
 ... and so on
 ></our-input>

There are use cases for this component where we don't want the hint to show. So, so long as you provide the hint string, our-input will show the our-hint component (which is nested inside the template).

But I could just as well have implemented the component to work like this:

<our-input
 [hideAssistiveText]="hideAssistiveText"
 [type]="inputType"
 [label]="label"
 [control]="control"
 ... and so on
 >
   <our-hint label="{{hint}}"></our-hint>
</our-input>

And the developer could just omit the our-hint component altogether to achieve the same thing.

What I'm after is some clear cut best practice resources around when to use one method over the other (if there is any) or reasons behind which method you have adopted.

2 Answers2

0

I feel there are two schools of thoughts here. One is how your components are being organized to structure your app and how you are managing their visibility toggling. Think there should a clear separation while addressing the two.

Rahul Wasnik
  • 142
  • 1
  • 5
  • Thanks for the reply, though this seems very specific to hiding and showing components. Could you extend your answer to answer the following: "Use an @Input when ..." and "Use a child component when ..."? – Jared Whittington Jan 29 '20 at 00:03
  • Hey Jared, I have modified my answer could you perhaps share what exactly is it that you are trying to achieve here. I mean if its just hiding something on the page based on some boolean value, would'nt a *ngIf suffice. – Rahul Wasnik Jan 29 '20 at 02:15
  • Sure I made a second edit and gave it another shot ^ – Jared Whittington Jan 29 '20 at 03:41
  • I c... I would follow the second approach since that makes our hint label component purely a presentation component whose job is to just display the hint passed to it. I can then treat this as I treat any third party component just like angular mat select or mat snackbar. Makes it reusable and easy to test. – Rahul Wasnik Jan 29 '20 at 07:08
0

From my experience there are a couple of cases where I would recommend Example component 1 over Example component 2.

  1. There are other inputs and outputs that the parent will pass to the child (or there could be at some point in the future).
  2. As you mentioned in your post, when the parent will always have the same child component and is not meant to support other types of children.

Example component 2 is better in cases where the parent is meant to be generic and able to have a variety of children (or could at some point in the future).

Other than that, there are no hard rules and this mostly comes down to personal preference. Either way, always consider how you may scale and use the component in the future.

Jacob McGowan
  • 592
  • 4
  • 10
  • Great answer, thank you. Just to confirm your first point, you're saying it would be tricky for the child component to communicate with the parent component directly because the childs inputs are bound to grandparent component, right? Great consideration indeed. – Jared Whittington Jan 29 '20 at 03:56
  • To clarify the first point, let's say you have a Contact component which has a child Address component in which you pass the address information of the contact to the address component. Using @Input is easier in this case. Whenever that is not the case, ngConent works fine. – Jacob McGowan Jan 29 '20 at 06:02