Angular 2/4 : How to check length of input's value using directive?

21,990

Solution 1

You can track the input length changes in DoCheck:

Directive

Directive({ selector: '[inputfocus]' })

export class InputFocusedDirective implements DoCheck
 {
   public valLength;
   @Input() inputfocus;
   constructor(public el: ElementRef, public renderer: Renderer) {}


   ngDoCheck(){
         let valLength = this.el.nativeElement.value.length;
         console.log("valLength "+ valLength );

        if (valLength > 0) {
           this.renderer.setElementClass(this.el.nativeElement.parentElement, 'focused', true);
        }
        else
        {
          this.renderer.setElementClass(this.el.nativeElement.parentElement, 'focused', false);
        }
    }
}

HTML

<div>
   <input [inputfocus]="fname" name="name" [(ngModel)]="fname" type="text">
</div>

CSS:

input{
  background-color:red;
}

.focused input{
  background-color:green;
}

stackblitz demo

Solution 2

If all you are trying to do is apply a class to the containing element when an input has some text inside it, you do not need a directive for this.

<div id="i-contain-the-input" [ngClass]="{'focused': myInputValue && myInputValue.length > 0}">
  <input [(ngModel)]="myInputValue" type="text">
</div>
<!-- myInputValue needs to be declared in your component -->

But if you absolutely must make a directive for this, then do the following:

@Directive({
  selector: '[inputfocus]',
})
export class InputFocusedDirective {

  constructor(private el: ElementRef, private render: Renderer) {
  }

  @HostListener('change') onChange() {
    if (this.el.nativeElement.value.length > 0) {
      this.renderer.setElementClass(this.el.nativeElement.parentElement, 'focused', true);
    }
  }

}

Solution 3

I have created a similar example.

import {Directive, ElementRef} from '@angular/core';

@Directive({
 selector: '[inputfocus]'
 })
export class DataDirective {

   constructor(private el: ElementRef) { 
     var elem = el.nativeElement.value;
    console.log(elem + "==> length = " + elem.length);
   }


}

in the html part

<input class="mask-text" value="hello" inputfocus type="text"/>

Demo http://plnkr.co/edit/JX6P1vnqUJEzL94BOFuO?p=preview

Share:
21,990

Related videos on Youtube

AmitV
Author by

AmitV

Updated on July 09, 2022

Comments

  • AmitV
    AmitV almost 2 years

    I've created one custom attribute directive that can validate input, It has value or not. Please refer below code.

    I don't know why if condition is not working, in console.log it is showing 0 only. is there anything wrong in my code?

    I tried with other angular's app lifecycle event too.

    Thanks!

    import { Directive, ElementRef, Input, AfterContentInit ,Renderer } from '@angular/core';
    
    @Directive({ selector: '[inputfocus]' })
    
    export class InputFocusedDirective implements AfterContentInit {
        public valLength;
    
        constructor(public el: ElementRef, public renderer: Renderer) {}
    
        ngAfterContentInit() {
    
            var valLength = this.el.nativeElement.value.length;
        consol.log("valLength "+ valLength );
    
            if (valLength > 0) {
               this.renderer.setElementClass(this.el.nativeElement.parentElement, 'focused', true);
            }
    
    
        }
    }
    
    • Aakash Jain
      Aakash Jain over 6 years
      Is your goal only to apply a class to the parent when the input element has something in it? Because that can be achieved in a much simpler manner, and using a custom directive for it is overkill.
    • AmitV
      AmitV over 6 years
      @Aakash, I'm using floating label type of input controls in my app and want to add focused class in edit mode. when there is value inside input, label should float to top.
    • Aakash Jain
      Aakash Jain over 6 years
      Can you add a snippet from your tempate code to show how your labels and inputs are arranged?
    • AmitV
      AmitV over 6 years
      @Vega, Your code is working fine on change event as you have shared. I wrapped input text inside div and then typing in input are adding and removing focused class based on if condition. please check stackblitz.com/edit/angular-axnchs?file=app%2Fapp.component.‌​ts. I want to update the same on component load that is when page get load, condition get check and class should remove or add to its parent div. I tried with ngOnInit() and ngAfterViewInit() but didn't work as expected.
    • AmitV
      AmitV over 6 years
      Thanks! Vega for your reply and seriously I appreciate your solution, [class.focused]="fname?.length>0" I know about this solution and other too but there are thousands of text and number controls on form and I want achieve the same by adding simple attribute directive(in my case it is inputfocus). this will work same as HTML5 "required" attribute that you just add it and it will do its job. second I will be able to learn how to use attribute directive with its customize power.
    • AmitV
      AmitV over 6 years
      what is new update dude? I'm not getting it.please help.
    • AmitV
      AmitV over 6 years
      Hey dude! I also tried the same added ngAfterViewChecked() and It worked. :-) :-) check here stackblitz.com/edit/angular-axnchs?file=app%2Fapp.component.‌​ts and you too did the same with some red highlight. now will check it inside project. thanks man :-)
    • AmitV
      AmitV over 6 years
      Please update your answer that you have submitted previously so that I can accept it as right solution.
  • AmitV
    AmitV over 6 years
    Thanks for your reply. In my app there are N no of input controls present. going for first approach will be lengthy. that is why I thought to create directive. I tried your code it is not working, please share working code on plunker if possible.
  • AmitV
    AmitV over 6 years
    @ Vega, Thanks, please visit this url stackblitz.com/edit/… are 3 text box two are with inputfocus directive and last one is without it. I created one more directive that is togglefocus.directive.ts that will host listener for focus & blur. try to focus on each text box u will notice in 2nd field focus is not working or I can say class is getting apply & removing instantly plz check DOM. 3rd field is getting focus and changing color based on focus and blur. I'm sure that If condition of DoCheck() is preventing it apply class on focus.
  • Vega
    Vega over 6 years
    @AmitV, I am not sure to understand :( Could you please explain me again but is the expected behaviour? What is your goal? To change the class(color) on focus/blur based on the condition?
  • AmitV
    AmitV over 6 years
    Okay, please click on each textbox and check behavior of them. I want to add and remove focused class based some logic please check togglefocus.directive.ts. logic is straight if text box has value and u are focusing out then don't remove focused class and vice versa. my problem is that inputfocus directive & @hostlistener both working fine individually but not together please check 2nd textbox behavior background is not getting green but without inputfocus directive 3rd txtbox is behaving perfectly.
  • Vega
    Vega over 6 years
    The second one should be green on focus? It's red because of empty value, but when it's not empty, it's green. Should the second one stay stay green, when empty but focued? The third follows the second directive logic, so it's good also. Please tell me just what you want as behaviour, not what is not working.
  • AmitV
    AmitV over 6 years
    My input controls are like floating label, on focus label moves to top and the same come down on blur if input don't have value thats why I've created that togglefocus.directive.ts. In edit mode when data come pre-field that time " inputfocus " directive that you shared with ngDoCheck() works and validate the field till this it is working fine. but when I'm removing character from txtbox and making it empty that time my hostlistner is not working properly and unable to add that focused class. in this case inputfocus directive and hostlistener are conflicting with each other as I found.
  • AmitV
    AmitV over 6 years
    Please do empty txtbox 1 and then focus on it you will see txtbox will not get focused class but in case of txtbox 3 it is working fine. on focus of txtbox 2 you can guess easily what is going wrong.
  • AmitV
    AmitV over 6 years
    did you understand my problem?
  • Vega
    Vega over 6 years
    oops, I saw just now this. I am taking a look right now :)
  • AmitV
    AmitV over 6 years
    I got the solution dude. Just added one more if condition.