8
\$\begingroup\$

I have a textarea and need to calculate how many characters have been typed into it.

Both of the following solutions work correctly—which would be preferable, and why? Is there an even better way to implement it?

Option A:

<textarea 
   id="descriptionEducation" 
   name="description" 
   rows="5" 
   [(ngModel)]="fruit.description"></textarea>

<div class="form-row__description">
    You have written {{ fruit.description.length }} characters
</div>

Option B:

<textarea 
   id="descriptionEducation" 
   name="description" 
   rows="5" 
   [ngModel]="fruit.description" #descriptionFruit></textarea>

<div class="form-row__description">
    You have written {{ descriptionFruit.value.length }} characters
</div>
\$\endgroup\$
1
  • 3
    \$\begingroup\$ What do you mean by character? UTF-16 code unit? Unicode codepoint? Grapheme cluster? \$\endgroup\$ Commented Aug 29, 2017 at 11:42

3 Answers 3

6
\$\begingroup\$

You don't need to declare an extra reference variable. I would suggest the first approach i.e. using [(ngModel)] for two-way data binding.

However, in the first approach, you must initialize the model value before using it in your template i.e. fruit.description should not be undefined otherwise you'll get the following TypeError:

Cannot read property 'length' of undefined

Using the second approach, you wont get that error.

\$\endgroup\$
7
  • \$\begingroup\$ Yes! You're right! we saw the error. How do you mean with initialize the model value? we tried to do it but still see the same error. Would be great if you could give an example. (sorry cannot reply directly, my reputation is < 50) \$\endgroup\$
    – iv444
    Commented Aug 30, 2017 at 11:44
  • \$\begingroup\$ @ivanasetiawan it means that fruit.description should be initialize e.g. if it is of type string, then fruit.description = ''; \$\endgroup\$
    – FAISAL
    Commented Aug 30, 2017 at 12:19
  • \$\begingroup\$ I added public fruit: any = { description: ''}; on .ts file but still see the error.. What am I missing? \$\endgroup\$
    – iv444
    Commented Sep 4, 2017 at 7:42
  • \$\begingroup\$ i dont see any erros, see this demo: stackblitz.com/edit/… \$\endgroup\$
    – FAISAL
    Commented Sep 4, 2017 at 7:46
  • 1
    \$\begingroup\$ Ok solved it! the problem occurred because the textarea is inside a tab element. Therefore we need to reinitialize the model value everytime a tab button is clicked. In this case, if we use optB we don't need to reinitialize it everytime. \$\endgroup\$
    – iv444
    Commented Sep 4, 2017 at 8:46
5
\$\begingroup\$

Both are indeed completely valid. But since Angular is a databinding framework I would suggest using the two-way binding directive [(ngModel)] to keep things more Angular.

\$\endgroup\$
1
\$\begingroup\$

I would go with Forms and will do it totally async way.

<textarea 
   id="descriptionEducation" 
   name="description" 
   rows="5" 
   [formControl]="textControl"></textarea>

<div class="form-row__description">
    You have written {{ descriptionLength | async }} characters
</div>

Inside of component

public textControl = new FormControl('');
public descriptionLength = new BehaviorSubject(0);
constructor(){
  this.textControl.valueChanges.subscribe((v)=> this.descriptionLength.next(v.length));
}

Now you can even mark you control ChangeDetectionStrategy.OnPush and it will work

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.