Search code examples
angularangular-forms

Emulating angular fancy inputs


The powers-that-be have decided, weeks before launch, that they like the modern look of input controls that are underlines rather than boxes, with the labels that slide out of the way when the input has focus.

This page demonstrates the effect: https://material.angularjs.org/latest/demo/input Click on First name to see the label move.

My reusable component looks like this:

<span 
    [ngClass]="styleClass" 
    class="wrapper">

    <label 
        [ngClass]="{'text-center': largeLabel, 'm-h-0': largeLabel}" 
        [attr.aria-labelledby]="id + '-label'">

        <span 
            [ngClass]="{'large-label': largeLabel}">
            {{ label }}
        </span>
    </label>

    <input 
        #element [value]="(isUppercase)?(textValue |uppercase): textValue" 
        (keyup)="onChange($event)" 
        (focusout)="executeAllTouchedFunctions(); 
        onChange($event)"
        [ngClass]="{'ng-invalid': !control?.valid && (control?.touched || control?.dirty) && !control.disabled, 'ng-dirty': control?.dirty, 'ng-touched': control?.touched}"
        [type]="type" 
        class="form-control" 
        [placeholder]="placeholder || ''" 
        [attr.aria-describedby]="(describedById) ? describedById : controlName?.name + '-described-by-id'"
        [name]="name" 
        [attr.aria-labelledby]="id + '-textField'" 
        [required]="isRequired" 
        [attr.maxlength]="maxlength" 
        [attr.aria-required]="isRequired"
        [disabled]="disabled" 
        (focus)="onFocus(e)" 
        [attr.aria-invalid]="!control?.valid && (control?.touched || control?.dirty)" />
</span>

So, as far as I can tell, to affect the label, when the input has focus, I'll need to use JavaScript (with some sort of $(input).parent().find(label)) thing.

I've added the onFocus() event, and am capturing the event, but not sure what to do with it.

onFocus(event:FocusEvent) {
    console.log(FocusEvent);
}

this simply returns

"FocusEvent() { [native code] }"

I was expecting some objects I could work with. Can I get hold of the input object in the DOM, so I can find its associated label?

Or am I overthinking this?


Solution

  • input controls that are underlines rather than boxes, with the labels that slide out of the way when the input has focus.

    This style of input field comes from Google's Material Design system.

    The Angular team created the Angular Material library so you don't have to implement these components yourself. Here's the documentation for <mat-form-field>.

    this simply returns

    "FocusEvent() { [native code] }"

    You are logging the constructor FocusEvent instead of logging your event object. If you change your code to console.log(event), you should get an object that looks like this:

    bubbles: false
    cancelBubble: false
    cancelable: false
    composed: true
    currentTarget: null
    defaultPrevented: false
    detail: 0
    eventPhase: 0
    isTrusted: true
    path: (9) [input.s-input.js-search-field., div.ps-relative, form#search.searchbar.js-searchbar, div.-container, header.top-bar.js-top-bar.top-bar__network._fixed, body.question-page.unified-theme, html.html__responsive, document, Window]
    relatedTarget: null
    returnValue: true
    sourceCapabilities: InputDeviceCapabilities {firesTouchEvents: false}
    srcElement: input.s-input.js-search-field.
    target: input.s-input.js-search-field.
    timeStamp: 100675.87499995716
    type: "focus"
    view: Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
    which: 0
    

    And you can access the input field as event.target.