Angular 2/4: как проверить длину входного значения с помощью директивы?

Я создал одну директиву пользовательского атрибута, которая может проверять ввод, имеет значение или нет. Пожалуйста, обратитесь к приведенному ниже коду.

Я не знаю, почему, если условие не работает, в console.log отображается только 0. что-то не так в моем коде?

Я пробовал и с другим событием жизненного цикла приложения angular.

Спасибо!

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);
        }


    }
}

person AmitV    schedule 21.09.2017    source источник
comment
Ваша цель только применить класс к родителю, когда в элементе ввода что-то есть? Потому что это может быть достигнуто гораздо более простым способом, и использование для этого пользовательской директивы является излишним.   -  person Aakash Jain    schedule 21.09.2017
comment
@Aakash, я использую элементы управления вводом с плавающей меткой в ​​​​своем приложении и хочу добавить сфокусированный класс в режиме редактирования. когда внутри ввода есть значение, метка должна плавать вверх.   -  person AmitV    schedule 21.09.2017
comment
Можете ли вы добавить фрагмент кода шаблона, чтобы показать, как устроены ваши метки и поля ввода?   -  person Aakash Jain    schedule 21.09.2017
comment
@Vega, ваш код отлично работает с событием изменения, которым вы поделились. Я обернул вводимый текст внутри div, а затем вводя ввод, добавляю и удаляю сфокусированный класс на основе условия if. пожалуйста, проверьте stackblitz.com/edit/angular-axnchs?file= приложение%2Fapp.component.ts. Я хочу обновить то же самое при загрузке компонента, то есть при загрузке страницы, проверке условия и классе, который должен удалить или добавить в свой родительский div. Я пробовал с ngOnInit() и ngAfterViewInit(), но не работал должным образом.   -  person AmitV    schedule 24.09.2017
comment
Спасибо! Vega за ваш ответ, и я серьезно ценю ваше решение, [class.focused]=fname?.length›0 Я знаю об этом решении и о других, но в форме есть тысячи текстовых и числовых элементов управления, и я хочу добиться того же, добавив простая директива атрибута (в моем случае это inputfocus). это будет работать так же, как обязательный атрибут HTML5, который вы просто добавляете, и он будет выполнять свою работу. во-вторых, я смогу научиться использовать директиву атрибута с ее мощностью настройки.   -  person AmitV    schedule 24.09.2017
comment
что за новое обновление чувак? Я не понимаю. Пожалуйста, помогите.   -  person AmitV    schedule 24.09.2017
comment
Привет чувак! Я также попробовал добавить ngAfterViewChecked(), и это сработало. :-) :-) проверьте здесь stackblitz.com/edit/ angular-axnchs?file=app%2Fapp.component.ts и вы тоже сделали то же самое с красным бликом. теперь проверим это внутри проекта. Спасибо чувак :-)   -  person AmitV    schedule 24.09.2017
comment
Пожалуйста, обновите свой ответ, который вы отправили ранее, чтобы я мог принять его как правильное решение.   -  person AmitV    schedule 24.09.2017


Ответы (3)


Вы можете отслеживать изменения длины ввода в DoCheck:

Директива

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

person Vega    schedule 21.09.2017
comment
@ Vega, спасибо, пожалуйста, посетите этот URL stackblitz.com /edit/ — это 3 текстовых поля, два из которых имеют директиву inputfocus, а последнее — без нее. Я создал еще одну директиву togglefocus.directive.ts, которая будет размещать прослушиватель для фокусировки и размытия. попробуйте сосредоточиться на каждом текстовом поле, которое вы заметите во втором поле, фокус не работает, или я могу сказать, что класс применяется и удаляется мгновенно, пожалуйста, проверьте DOM. 3-е поле получает фокус и меняет цвет в зависимости от фокуса и размытия. Я уверен, что если условие DoCheck() мешает ему применить класс в фокусе. - person AmitV; 25.09.2017
comment
@AmitV, я не уверен, что понимаю :( Не могли бы вы объяснить мне еще раз, но это ожидаемое поведение? Какова ваша цель? Изменить класс (цвет) фокуса / размытия в зависимости от условия? - person Vega; 25.09.2017
comment
Хорошо, пожалуйста, нажмите на каждое текстовое поле и проверьте их поведение. Я хочу добавить и удалить сфокусированный класс на основе некоторой логики, пожалуйста, проверьте togglefocus.directive.ts. логика прямая, если текстовое поле имеет значение, и вы фокусируетесь, то не удаляйте сфокусированный класс, и наоборот. Моя проблема в том, что директива inputfocus и @hostlistener работают нормально по отдельности, но не вместе. Пожалуйста, проверьте, что фон поведения второго текстового поля не становится зеленым, но без директивы inputfocus 3-й текстовый блок ведет себя отлично. - person AmitV; 25.09.2017
comment
Второй должен быть зеленым в фокусе? Он красный из-за пустого значения, но когда он не пуст, он зеленый. Должен ли второй оставаться зеленым, когда он пуст, но сфокусирован? Третий следует логике второй директивы, так что это тоже хорошо. Пожалуйста, скажите мне, что вы хотите в качестве поведения, а не то, что не работает. - person Vega; 25.09.2017
comment
Мои элементы управления вводом похожи на плавающую метку, при фокусе метка перемещается вверх и то же самое опускается при размытии, если ввод не имеет значения, поэтому я создал этот togglefocus.directive.ts. В режиме редактирования, когда данные поступают в предварительное поле, директива time inputfocus, которой вы поделились с ngDoCheck(), работает и проверяет поле до тех пор, пока оно не будет работать нормально. но когда я удаляю символ из txtbox и делаю его пустым, мой hostlistner не работает должным образом и не может добавить этот сфокусированный класс. в этом случае директива inputfocus и hostlistener конфликтуют друг с другом, как я обнаружил. - person AmitV; 25.09.2017
comment
Пожалуйста, сделайте пустой txtbox 1, а затем сосредоточьтесь на нем, вы увидите, что txtbox не получит сфокусированный класс, но в случае txtbox 3 он работает нормально. в фокусе txtbox 2 вы можете легко догадаться, что происходит не так. - person AmitV; 25.09.2017
comment
ты понял мою проблему? - person AmitV; 25.09.2017
comment
ой, только сейчас увидел это. щас присматриваюсь :) - person Vega; 26.09.2017
comment
У меня есть решение, чувак. Просто добавил еще одно условие if. - person AmitV; 02.10.2017

Если все, что вы пытаетесь сделать, это применить класс к содержащему элементу, когда внутри ввода есть некоторый текст, вам не нужна для этого директива.

<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 -->

Но если вам абсолютно необходимо сделать для этого директиву, то сделайте следующее:

@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);
    }
  }

}
person Aakash Jain    schedule 21.09.2017
comment
Спасибо за ваш ответ. В моем приложении нет N элементов управления вводом. переход к первому подходу будет длительным. вот почему я подумал создать директиву. Я попробовал ваш код, он не работает, пожалуйста, поделитесь рабочим кодом на plunker, если это возможно. - person AmitV; 21.09.2017

Я создал аналогичный пример.

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);
   }


}

в html части

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

Демо http://plnkr.co/edit/JX6P1vnqUJEzL94BOFuO?p=preview

person Arjun Nayak    schedule 21.09.2017