2

On teh second time setting visibility of textarea component it throws the error mentioned in the title. Here is a plunker to demonstrate the problem: https://plnkr.co/edit/jW4KXfsI7WLgQxI1ne0r?p=preview The problematic component's code:

import {Component, OnInit, ElementRef, ViewChild, Input, forwardRef, ChangeDetectorRef} from "@angular/core";
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from "@angular/forms";

const noop = () => {
};

export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => TextareaComponent),
  multi: true
};

@Component({
  selector: 'app-textarea',
  templateUrl: './textarea.component.html',
  styleUrls: ['./textarea.component.scss'],
  providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
})
export class TextareaComponent implements OnInit, ControlValueAccessor  {

  private _value = '';
  private _defaultLimit: number = 200;
  @Input('charLimit')
  private _charLimit: number;
  @Input('lineLimit')
  private _lineLimit:number;
  @Input('doLimitChar')
  private _doLimitChar: boolean = true;
  @ViewChild('storyText')
  private _textAreaElement: ElementRef;
  private _disabled: boolean = false;
  /** Callback registered via registerOnTouched (ControlValueAccessor) */
  private _onTouchedCallback: () => void = noop;
  /** Callback registered via registerOnChange (ControlValueAccessor) */
  private _onChangeCallback: (_: any) => void = noop;

  constructor(private _crf:ChangeDetectorRef) {
  }

  ngOnInit() {
    this._charLimit = this._charLimit || this._defaultLimit;
  }

  get value():any {
    return this._value;
  }

  set value(v: any) {
    if (!v) v = "";
    if (this._doLimitChar) {
      v = v.substring(0, this._charLimit);
    }
    this._value = v;
    this._textAreaElement.nativeElement.value = v;
    this._onChangeCallback(v);
  }

  // get empty() {
  //   return ( this.value == null || this.value === '')
  // }
  //
  // get charCount(): number {
  //   return this.empty ? 0 : ('' + this.value).length;
  // }

  get remainingCharacterCount(): number {
    return this._charLimit - this.value.length;
  }

  get linesNumber():number {
    return this.value.split('\n').length;
  }

  /** Implemented as part of ControlValueAccessor. */
  writeValue(value: any) {
    this.value = value;
  }

  /** Implemented as part of ControlValueAccessor. */
  registerOnChange(fn: any) {
    this._onChangeCallback = fn;
  }

  /** Implemented as part of ControlValueAccessor. */
  registerOnTouched(fn: any) {
    this._onTouchedCallback = fn;
  }

  /** Implemented as a part of ControlValueAccessor. */
  setDisabledState(isDisabled: boolean) {
    this._disabled = isDisabled;
  }

}
2
  • 1
    The problem is in Story.tldr property. You can set initial value to '' for this plnkr.co/edit/FUTWfhlbTDjIIrQPqpAx?p=preview Commented Feb 4, 2017 at 19:50
  • So it won't change between undefined and ' ', ahaa. Commented Feb 5, 2017 at 7:01

1 Answer 1

2

I don't know what exactly causes the error but detectChanges() fixes it

  toggleTldr() {
    this.isTldrVisible = !this.isTldrVisible;
    this.crf.detectChanges();
  }

Plunker example

The difference to markForCheck() is, that detectChanges() runs change detection immediately.

I guess the root cause is that you mix template-driven (ngModel) and reactive forms (FormBuilder).

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.