Search code examples
angularangular2-directives

Angular 2 - Why can't you log out the input value


I feel like I must be missing something here and would like to find out if there is a better way of doing this.

I've got a directive that basically adds a class to the parent element of a input field. On load I need to check if the input field has a value, you'd think that would be simple...

I've used a few different options now which include, ngOnInit, AfterContentInit and AfterViewInit. But for the below I'm still on AfterContentInit:

ngAfterContentInit() {
  console.log(this.el.nativeElement); // Element Object "Value is not empty if you look inside the object."
  console.log(this.el.nativeElement.value); // = ''

  setTimeout(() => {
    console.log(this.el.nativeElement.value); // = 'The Value!'
  }, 1000);

  this.activeStateCheck(this.el.nativeElement);
}

activeStateCheck(element) {
  if (element.value !== '') {
    element.parentElement.classList.add('active');
    return true;
  }
}

I should point out that all options give the same results.

The first console logs out an empty string and the second one logs out the actual string. In this case it is 'Grand Tour'.

My question is how do I do this without using a setTimeout?

It appears to have to wait for the data to load on the page before it you can log the value. However I was under the impression that OnInit was meant to wait for this to be finished?

The reason why I'd like to find a better solution is because if the page takes longer than a second to load then the console log will output an empty string, therefore not a complete solution.

This is an example of the directive being called. Notice the appPlaceholder attribute:

<fieldset class="form__placeholder">
    <input type="text" 
            id="lastName" 
            formControlName="lastName" 
            appPlaceholder>
    <label for="lastName"
           class="form__placeholder--label">
      Lastname:
    </label>
</fieldset>

Solution

  • From what you've told us, I'm not sure you need a custom directive. If you truly want to add the class "active" to the parent of a non-empty input, you can simply do

    <div [ngClass]={'active': groupForm.get('name').value !== ''}>
      <input formControlName="lastName">
    </div>
    

    You can even omit the !== '' as an empty string is falsy.

    If you absolutely need a directive for some other reason, you can treat formControlName as an input to your directive, @Input() formControlName;, but if you do that, you'll also need to pass the formGroup in. Changing parent behavior from a child seems messy, however, expecially with direct DOM manipulation like you're doing (use HostBinding instead). I'd probably suggest pairing the parent/input combination into a new component instead.