Tag: input

  • Celebrate independence with a completely self-sufficient Angular button that can hide any parent

    Celebrate independence with a completely self-sufficient Angular button that can hide any parent

    One of the most fun things about Angular – yes, I said fun AND I’m not being sarcastic – is coming up with ways to create components that are totally modularized and can perform functions with a plug-and-play attitude. For example, I created a button that can hide any parent just by including its component within the component you’re trying to hide.

    Start with a generic button component

    At the heart of every good component are the absolute bare-minimum basics. If you want to take advantage of a modular approach, make sure you are using building blocks that are flexible enough to build upon and that are loosely coupled so that they won’t become restrictive later on. In other words, you want to build components that you can confidently change because you know those changes will be isolated and not cause unintended ripple effects.

    So, the first step is to create a button component that will be the foundation of all of your other buttons. For example, below is the base button component I use for my blog’s website. It gives the developer an option to add whatever content they want for the button, as indicated by Angular’s “ng-content” tag.

    button.component.html

    <button [ngClass]="class" [disabled]="disabled">
      <ng-content></ng-content>
    </button>
    

    Add CSS to your button

    button.component.scss

      @import "src/assets/styles/variables.scss";
    
      button {
        font-size: inherit;
        background: inherit;
        color: inherit;
        text-align: center;
        padding: 0.5em 1.0em;
        border: 1px solid;
        border-radius: $border-radius;
      }
      button:hover {
        filter: brightness(125%);
        cursor:pointer;
      }
    
      button.large {
        padding: 1.0em 2.0em;
        font-size: 2.0em;
        border: $border;
        border-radius: $border-radius;
      }
    
      button.no-border {
        border:0;
      }
    
      button.no-padding {
        padding:0;
      }
    
      .icon {
        width: 3.0em;
        height: 3.0em;
      }
    
      button:disabled {
        opacity: 0.25;
      }
    

    The developer can disable the button by setting the disabled property to true. I added CSS to make the disabled button have an opacity of 0.25 so that it appears disabled as well.

    Instead of hardcoding a color for the hover state, I am setting a filter to make the brightness at 125% so that it can apply to any button no matter what color it is. I also added the cursor to change to the hand, or more precisely pointer, upon hover since that’s not a default behavior.

    The developer can also choose to not have a border or padding.

    button.component.ts

      import { Component, Input } from '@angular/core';
    
      @Component({
        selector: 'ces-button',
        templateUrl: './button.component.html',
        styleUrls: [
          './button.component.scss'
        ]
      })
      
      export class ButtonComponent {
        @Input() class:string;
        @Input() disabled:boolean;
       }
    

    Next, create the button that can hide its parent

    I added inputs for the user to pass the label and opt for the default icon if desired. (This is useful if the developer wants to use the styles that are applied to the button, e.g., font size, padding, icon size, etc.)

    button-hide-parent.component.html

      <ces-button type="button" class="no-border no-padding" (click)="onClose()">
        <span *ngIf="label" class="label">{{ label }}</span>
        <ces-svg-x-circle class="button-close-icon"></ces-svg-x-circle>
      </ces-button>
    

    button-hide-parent.component.ts

      import { Component, Input, Renderer2, ElementRef, Output, EventEmitter } from '@angular/core';
    
      @Component({
        selector: 'ces-button-hide-parent',
        templateUrl: './button-hide-parent.component.html',
        styleUrls: ['./button-hide-parent.component.scss']
      })
      export class ButtonHideParentComponent  {
        @Input() icon: string;
        @Input() label:string;
        @Output() hidden: EventEmitter<any> = new EventEmitter();
    
        constructor(
          private renderer:Renderer2,
          private elem:ElementRef
        ) { }
    
      onClose() {
        const parent = this.renderer.selectRootElement(this.elem.nativeElement.parentNode);
        this.renderer.setStyle(parent, 'display', 'none')
        this.hidden.emit();
      }
    }
    

    By creating an instance of ElementRef, I’m able to easily obtain a reference to the component and therefore get the component’s parent without having to query the DOM. By using Renderer2, I’m able to safely target the parent component and apply the style “display:none.”

    I also added an EventEmitter just in case the parent needs to know that the parent was hidden.

    Use the new button

    To use the new button, include the selector in the HTML template of the component you would like to hide. No additional code is required to make it work.

    Note: You can specify another click event handler on the button in case you want to add another function in the parent’s typescript file. By doing so, clicking the button will invoke both the child’s and parent’s methods.