Implement real-time word counting in Angular as users type

  1. I am looking to monitor word count in real-time as a user enters text into a textarea field
  2. If the word limit of 100 is exceeded, further typing should be restricted
  3. I aim to display the word count dynamically as the user types

wordCounter()

 This function calculates the number of words entered in the textarea:
    this.wordCount = this.text ? this.text.split(/\s+/) : 0;
    this.words = this.wordCount ? this.wordCount.length : 0;

  }

This function efficiently counts the words

sample.component.html

<textarea [(ngModel)]="text" ng-change="wordCounter()" id="wmd-input" name="post-text" class="wmd-input s-input bar0 js-post-body-field processed" data-post-type-id="2" cols="92" rows="15" tabindex="101" data-min-length="" oncopy="return false;" onpaste="return false;" oncut="return false;"></textarea>

<div>Words:<span id="wordCount">{{ words }}</span></div>

This snippet showcases the HTML code for monitoring word count. Any advice or guidance on this task is greatly appreciated. Thank you!

Answer №1

To retrieve text from a textarea using the `keydown` event, utilize `ViewChild`

Update: To restrict the input to 100 words, you can disable the textarea by adding `[attr.disabled]="words >100 ? '' : null"`

Sample HTML code:

<textarea [attr.disabled]="words >100 ? '' : null" (keydown)="wordCounter()" #text id="wmd-input" name="post-text" 
class="wmd-input s-input bar0 js-post-body-field processed" data-post-type-id="2" cols="92" rows="15" tabindex="101" data-min-length="" oncopy="return false;" onpaste="return false;" oncut="return false;"></textarea>

    <div>Words:<span id="wordCount">{{ words }}</span></div>

Corresponding TypeScript code:

export class AppComponent {
  wordCount: any;

  @ViewChild("text") text: ElementRef;
  words: any;
  wordCounter() {
    //alert(this.text.nativeElement.value)
    this.wordCount = this.text ? this.text.nativeElement.value.split(/\s+/) : 0;
    this.words = this.wordCount ? this.wordCount.length : 0;
  }
}

View the live demo at https://stackblitz.com/edit/angular-word-count

Answer №2

To meet your requirement, you can utilize Angular Reactive Form control along with its disable() function. Here is an example to help you achieve this:

Controller

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';

@Component({
  selector: 'input-autosize-textarea-example',
  templateUrl: './input-autosize-textarea-example.html',
  styleUrls: ['./input-autosize-textarea-example.css'],
})
export class InputAutosizeTextareaExample implements OnInit {
  public remainingWords = 100;

  public textareaForm = new FormGroup ({
    textinput: new FormControl()
  });

  ngOnInit() {
  }

  wordCounter() {
    this.remainingWords = this.textareaForm.value ? 100 - this.textareaForm.value.textinput.split(/\s+/).length : 100;
    if (this.remainingWords <= 0) {
      this.textareaForm.controls['textinput'].disable();
    }
  }
}

Template

<form [formGroup]="textareaForm">
  <textarea 
    formControlName="textinput"
    (keyup)="wordCounter()" 
    id="wmd-input" 
    name="post-text" 
    class="wmd-input s-input bar0 js-post-body-field processed" 
    data-post-type-id="2" 
    cols="92" rows="15" 
    tabindex="101" 
    data-min-length="" 
    oncopy="return false;" 
    onpaste="return false;" 
    oncut="return false;"></textarea>
</form>
<div style="font-style: italic;">
  {{ remainingWords }} words remaining...
</div>
<br>
{{textareaForm?.value | json}}

The ?. operator is known as the safe navigation operator in Angular and it ensures that objects are defined before accessing their properties.

See a working example here: Stackblitz

Answer №3

For the solution, please refer to this link: https://codesandbox.io/s/damp-mountain-0vpe3

Simply follow these steps:

In your app.module.ts:

  1. import { FormsModule } from "@angular/forms"
  2. Add FormsModule to the imports array like this -
    imports: [BrowserModule, FormsModule]

Next, implement ngModel binding in app.component.html

<div>
  <div>
    <h2>Enter text here:</h2>
    <input type="text" [(ngModel)]="myText" placeholder="Type here..." />
  </div>
  <br /><br />
  <div class="wordCount">
    <div>
      Your Text: <span><b> {{myText}} </b></span> <br />
      <br />
      Count: <span><b> {{myText.length}} </b></span>
    </div>
  </div>
</div>

Screenshot:-

https://i.sstatic.net/ebN7p.png

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What methods can I use to dismantle an Angular component?

I have created a modal as a component called <modal-component>. Within the <modal-component>, there is a close button. I am looking for a way to completely remove the <modal-component> when this close button is clicked. I envision somet ...

What is the reason behind the failure of a react factory method compilation when extending a typescript class, despite it working perfectly fine on the base class?

As I delve into my lengthy codebase consisting of hundreds of lines, I have managed to narrow down my issue to a concise example. My query pertains to the peculiar behavior exhibited by the Typescript compiler in a specific scenario. The snippet below com ...

Problem with Typescript: The type '{ x;y }' is required to have a '[Symbol.iterator]()' method

Just starting out with Typescript and tackling the task of converting a React project from JavaScript to TypeScript. I've been diving into various posts for guidance, but I feel like I'm going in circles. Any assistance would be greatly appreci ...

Every time a new message is sent or received, I am automatically brought back to the top of the screen on the

I'm currently working on integrating a chat feature into my Angular Firestore and Firebase app. Everything seems to be functioning well, except for one issue - whenever a new message is sent or received, the screen automatically scrolls up and gets st ...

Unable to utilize the Object.values method with an object in TypeScript

I am attempting to create an array of values from all the keys within an object by using the Object.values(obj) function, but I encountered the following error message: No overload matches this call. Overload 1 of 2, '(o: { [s: string]: string; } | ...

Error Passing Data to Child Component in Typescript on Next.JS 14 Compilation

Although there are many similar questions, I am struggling to make my code work properly. I recently started learning typescript and am having trouble passing data to the child component. While the code runs fine in development (no errors or warnings), i ...

Attempting to execute the command "ionic serve" results in the display of various error messages

When attempting to run “ionic serve”, I encountered the following errors: [ERROR] ng has unexpectedly closed (exit code 127) https://i.sstatic.net/xgeb7.jpg Thank you in advance. ...

What is the best way to implement a switch case for the value of a property within an object in a TypeScript file?

The object I'm dealing with looks like this: {a: auth?.type === '1' || auth?.type === '2' || auth?.type === '3' ? { reason: // I need to implement a switch case here : un ...

What steps should I take to resolve the error message "ESLint encountered an issue determining the plugin '@typescript-eslint' uniquely"?

Struggling to enable eslint linting in an ASP.NET Core MVC project that incorporates React.js and typescript? I'm facing a tough challenge trying to resolve the error mentioned above. In my setup, I'm using Visual Studio 2022 Community Edition 1 ...

Guide to modifying the root directory when deploying a Typescript cloud function from a monorepo using cloud build

Within my monorepo, I have a folder containing Typescript cloud functions that I want to deploy using GCP cloud build. Unfortunately, it appears that cloud build is unable to locate the package.json file within this specific folder. It seems to be expectin ...

How to turn off automatic password suggestions in Chrome and Firefox

Currently, I have integrated a 'change password' feature which includes fields for 'old password', 'new password', and 'retype password'. However, the autocomplete feature is suggesting passwords from other user acco ...

What return type should be used when returning `_.orderBy` from a TypeScript function?

The current packages I have installed are lodash and @types/lodash. In my code, I am using: import _ from 'lodash'; function doSomething(): string[] { const letters = ['c', 'a', 'b']; return _.orderBy(letters ...

Angular predictive text selection menu

I'm trying to implement an input field with autocomplete functionality. The goal is to have the input field display dropdown values retrieved from a database as I type in it. I've been attempting to achieve this using angular material, but so far ...

Issue with running tests on Angular Material components causing errors

Running ng test on my Angular 8 project with Angular material components is resulting in multiple failures. The issue seems to be related to missing test cases for these scenarios. DeleteBotModalComponent > should create Failed: Template parse errors: & ...

NPM: There are no valid TypeScript file rules specified

Currently working on a small project using React.JS. Whenever I execute : npm run start, the following message gets logged: Starting type checking and linting service... Using 1 worker with 2048MB memory limit Watching: /Users/John/Projects/myProject/src ...

Retrieve the object from the data received from the HTTP GET API call

I have a question that has been asked before, but I am unable to achieve the desired result with my current approach. When my service retrieves data from an API, it returns results in the following format: { "nhits": 581, "paramete ...

The angular core module is displaying an inaccurate peer dependency warning regarding zone.js

Encountered this error message when trying to update my Angular version: @angular/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e88b879a8da8d9d8c6d9c6dd">[email protected]</a>" has an incorrect peer dependency ...

Incorporating Bloodhound into an Angular 2 CLI project

I have been working on integrating Bloodhound.js into an Angular 2 project that utilizes Angular 2 CLI. Currently, I have successfully implemented jQuery by following these steps: Installed jQuery using npm install jquery --save Installed jQuery Type ...

What is the best approach for unit testing with a subscribe in Angular 5?

import { Component, Input, OnInit } from '@angular/core'; import {DataplansDetails} from '../../models/dataplans-details'; import * as _ from "lodash"; @Component({ selector: 'jsonform', templateUrl: './jsonform.comp ...

What methods does TypeScript use to verify primitive types during runtime?

Is it true that Typescript removes any type or interface at compile time? If so, how is it possible to determine an object's primitive type using the typeof keyword? Are custom interfaces handled differently than primitive types? const a = "strin ...