0

I am using a strip down version of MDBootstrap(A) for material design on fields. In one field after pressing reset button, the value is pre-filled. But the animation of the label is not activated when that happens so the value and label is overlapping.

By the way this happens when the page is first loaded. It actually works when it is loaded with a value in, but doesn't work when I delete the value goes to invalid then I reset the the fields with the button. Value comes back but the activation of label for animation does not happen. May be it is CSS issue.

<div class="md-form form-group">
               <input  type="text"
                       id="portalName"
                       mdbActive
                       [ngClass]="{'invalid':(portal.errors && portal.touched) || (portal.errors && portal.dirty), 'valid':(!portal.errors && portal.touched) || (!portal.errors && portal.dirty)}"
                       class="form-control"
                       name="portalName"
                       [(ngModel)]="portalName.companyName"
                       #portal="ngModel"
                       [maxlength]="12"
                       required />
                <label for="portalName">{{"CUSTOM_BRANDING.LABELS.BESPOKE_NAME" | translate }}</label>

                <div *ngIf="portal.errors && (portal.dirty || portal.touched)"
                     class="message position-absolute">
                    <div [hidden]="!portal.errors.required" class="error-message" >
                        {{"CUSTOM_BRANDING.ERRORS.REQUIRED" | translate }}
                    </div>
                    <div [hidden]="!portal.errors.maxlength" class="error-message" >
                        {{"CUSTOM_BRANDING.ERRORS.MAX_LENGTH" | translate }}
                    </div>
                </div>
            </div>

I have to say I am pretty new with angular 2. I am trying to create something inside the component that when reset happens and value is filled in at least do a check on the field like setTouched or reset. Not sure what is best. I have this code in the component controlling the template

 resetCustBrand = (): void => {
    this.facade.resetBrandLogoAndName(this.facade.CommonNodeModel.SelectedNode.Id)
        .subscribe({
            complete: () => {
                this.selectedNodeChanged(this.facade.CommonNodeModel.SelectedNode);
                this.translator.getTranslationBaseOnKey("CUSTOM_BRANDING.TOASTER_RESET_BRANDING").subscribe((message: string) => {
                    const toasterMessage = message.split(',');
                    this.toaster.pop("success", toasterMessage[0], toasterMessage[1]);
                });
            },
            error: () => this.translator.getTranslationBaseOnKey("CUSTOM_BRANDING.ERRORS.RESETING_BRANDING").subscribe((errorMessage: string) => this.notifyService.notifyUser(errorMessage))
        });
}

I am hoping I may add something here to set the field again.

tekin
  • 145
  • 4
  • 15

2 Answers2

1

The label should be active when the field is pre-filled/ filled.

You can try the below mentioned code:

<label class="active" *ngIf="portalName != null; else not">  <!-- portalName should be replace with your data on input -->
  {{"CUSTOM_BRANDING.LABELS.BESPOKE_NAME" | translate }}  <!-- Your label Name -->
</label>

<ng-template #not>
  <label class="">
    {{"CUSTOM_BRANDING.LABELS.BESPOKE_NAME" | translate }}  <!-- Your label Name -->
  </label>
</ng-template>

This approach solved my issue.

  • Actually the new version of MD Bootstrap is solving this issue. Please see below answer. – tekin Dec 21 '18 at 16:35
0

MD bootstrap 5.2.3 is fixing this issue bu using AfterViewCheck life cycle hook and doing another initialise on the input onAfterViewCheck.

This is further handled in newer upgrades with DoCheck. We can not upgrade further than 5.3.2 because then you need angular 6 on your application.

But we created workaround with this code.

import {AfterViewInit, Directive, DoCheck, ElementRef, HostListener, 
Input, Renderer2} from '@angular/core';

@Directive({
selector: '[mdbActive]'
})    
export class ActiveDirective implements AfterViewInit, DoCheck {

public el: ElementRef;
public elLabel: ElementRef;
public elIcon: Element;

constructor(el: ElementRef, public renderer: Renderer2) {
    this.el = el;
}

@HostListener('focus', ['$event']) onClick() {
    this.initComponent();
}

@HostListener('blur', ['$event']) onBlur() {
    this.checkValue();
}

@HostListener('change', ['$event']) onChange() {
    this.checkValue();
}

ngDoCheck() {
    this.checkValue();
}

ngAfterViewInit() {
    this.initComponent();
    this.checkValue();
    setTimeout(() => {
        this.checkValue();
    }, 0);
}

private initComponent(): void {
    let inputId;
    let inputP;

    try {
        inputId = this.el.nativeElement.id;
    } catch (err) {}

    try {
        inputP = this.el.nativeElement.parentNode;
    } catch (err) {}


    this.elLabel = inputP.querySelector('label[for="' + inputId + '"]') || inputP.querySelector('label');
    if (this.elLabel != null) {
        this.renderer.addClass(this.elLabel, 'active');
    }

    this.elIcon = inputP.querySelector('i') || false;

    if (this.elIcon) {
        this.renderer.addClass(this.elIcon, 'active');
    }
}

// May need to change to public so can be called from component.
// This may be required so that changes applied after losing focus (e.g. typeahead) can be checked for
// if the ngDoCheck event doesn't fire.
private checkValue(): void {
    let value = '';
    if (this.elLabel != null) {
        value = this.el.nativeElement.value || '';
        if (value === '') {
            this.renderer.removeClass(this.elLabel, 'active');
            if (this.elIcon) {
                this.renderer.removeClass(this.elIcon, 'active');
            }
        } else {
            this.renderer.addClass(this.elLabel, 'active');
        }
    }
}

}

tekin
  • 145
  • 4
  • 15