Break up every word into its own separate <span>

I am currently facing an issue with displaying an array of strings in HTML using spans. These spans are wrapped inside a contenteditable div. The problem arises when a user tries to add new words, as the browser tends to add them to the nearest existing span instead of creating a new one for each word.

To display the span tags, I am utilizing *ngFor in my code. I update the array to reflect changes in the DOM, but unfortunately, the updated array is not being reflected in the HTML.

HTML Code

<div contenteditable="true" [id]="'data-section'+i">
  <ng-container *ngFor="let word of captionData.caption; trackBy:identify; let j = index">
    <span #caption [innerHTML]="word | punctuation" [id]="+i+'-'+j"></span>
  </ng-container>
</div>

TS Code

separateSpans(event: any, index: any) {

  const html: any = document.getElementById('data-section' + index)!;
  let spans = html.getElementsByTagName("span")!;
  let newArray: any = [];
  for (let i = 0; i < spans.length; i++) {
    let innerTextSpan: any = spans[i]?.innerHTML.trim().split(/\s+/);
    // If span has multiple words, then push the words individually
    if (innerTextSpan.length > 1) {
      for (let j = 0; j < innerTextSpan.length; j++) {
        spans[i].innerHTML = innerTextSpan[j]
        newArray.push(innerTextSpan[j])
      }
    } else {
      newArray.push(innerTextSpan[0])
    }
  }

  this.captionListData[index].caption = newArray; // Assign the new array to current array so that the current HTML dom also should be refresh with new spans
}

The original text had each word in a separate span.

The initial text:

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

After adding new words and running the mentioned function, the added words appear twice.

After adding new words:

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

In the image above, you can see that instead of each word being bound to a separate span, both old and new spans are displayed simultaneously, resulting in duplicates. I am unsure how to resolve this issue.

Goal: My objective is to have each word separated into its own span. For example, if a span contains 2 words like

<span>Demo text</span>
, after running the function it should become
<span>Demo</span><span>text</span>
. Please advise if there are any missing elements or if another approach should be considered.

Answer №1

At this moment, your current code is replacing a span element with multiple words with only the last word instead of the first.

To fix this issue,

spans[i].innerHTML = innerTextSpan[j]

should be changed to

spans[i].innerHTML = innerTextSpan[0] 

and should be moved outside of the loop.

The corrected snippet should look something like this:

if (innerTextSpan.length > 1) {
    spans[i].innerHTML = innerTextSpan[0];
    for (let j = 0; j < innerTextSpan.length; j++) {
      newArray.push(innerTextSpan[j])
    }
} 

I have tested this solution by simplifying your HTML structure, and it works perfectly:

<div contenteditable="true" id="data-section">
  <ng-container *ngFor="let word of captionListData">
    <span [innerHTML]="word"></span>
  </ng-container>
</div>

Lastly, within the TypeScript function, make sure to update: this.captionListData = newArray;

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

Resetting the selected options in AngularJS dropdown lists

Utilizing ng-repeat in my HTML code to iterate over a JavaScript array and displaying it within a selection. I am trying to achieve the functionality of clearing all selected data from these dropdown lists when a button is clicked. Snippet of HTML: <d ...

Unforeseen behavior in event binding causing knockout knockout

I implemented an event binding for the scroll event on a DIV. To add debounce functionality to the handler, I created a function on my model that generates the debounced handler. Then, in my view, I bind this factory function. I assumed that my factory fu ...

Received an error while attempting to install react-router-dom

I keep encountering this error message whenever I try to install react-router-dom using NPM in VS Code: https://i.sstatic.net/hFshb.png npm ERR! Unexpected end of JSON input while parsing near '...stack-launcher":"^1.0' npm ERR! You can find ...

angular 2 : Unable to locate the variable named 'Response'

I encountered an issue while working on my angular 2 project: Error: Cannot find name 'Response'. The error seemed to originate from the following service: import { Injectable } from '@angular/core'; import { Http } from '@ang ...

Beware of the 'grid zero width' alert that may appear when utilizing ag-Grid's sizeColumnsToFit() function on multiple ag-Grids that are shown within a tab menu

Encountering a warning message when resizing ag-Grid and switching between tabs. The warning reads: ag-Grid: tried to call sizeColumnsToFit() but the grid is coming back with zero width, maybe the grid is not visible yet on the screen? A demo of this ...

Combine two or more Firebase Observables

Currently, I am working on creating an Observable using FirebaseObjectObservable. However, before I can accomplish this, I need to query a Firebase list to obtain the key IDs required for the FirebaseObjectObservable. The structure of my data is as follow ...

What does ngModel look like without the use of square brackets and parenthesis?

Can you explain the usage of ngModel without brackets and parentheses in Angular? <input name="name" ngModel> I am familiar with [ngModel] for one-way binding and [(ngModel)] for two-way binding, but I am unsure what it means when ngModel ...

A streamlined method to verify the presence of a username or email address in MongoDB before registering

I'm currently running a NodeJS server with ExpressJS to manage my /register route. As part of the registration process, I need to confirm that both the user's username and email are unique before allowing them to create an account in the users co ...

Is it possible to implement UseState in Server-Side-Rendering scenarios?

Is it possible to utilize useState (and other react hooks?) with Server Side Rendering? I keep encountering the following error when attempting to execute the code: TypeError: Cannot read property 'useState' of null. Oddly enough, if I disable ...

Conceal only the anchor tag's text and include a class during the media query

In the anchor tag below, I have a text that says "Add to cart," but on mobile view, I want to change it to display the shopping cart icon (fa fa-cart). <a class="product"><?php echo $button_add_to_cart ?></a> Currently, the variable $bu ...

Submitting a form through Ajax is resulting in multiple submissions

Whenever I use Ajax to submit this form, it ends up posting multiple times without any obvious reason. Sometimes, it posts the form up to 10 times even though the submit button is clicked only once. I'm puzzled as to why this behavior is happening. An ...

Solving the Issue of Assigning a Random Background Color to a Dynamically Created Button from a Selection of Colors

Trying to create my own personal website through Kirby CMS has been both challenging and rewarding. One of the features I'm working on is a navigation menu that dynamically adds buttons for new pages added to the site. What I really want is for each b ...

Choose everything except for the information determined by the search

Currently facing an issue with the select all functionality. I found a code snippet on this link but it's not exactly what I need. I want to modify the select all feature so that it is based on the search value. For instance, if I have a set of data ...

How do I activate the <li> tag using jQuery?

I am currently implementing pagination on my webpage using the following JavaScript code: var pagingList = $('<ul>', {class: 'pagination list-unstyled list-inline'}); ...

What are some strategies for circumventing the need for two switches?

My LayerEditor class consists of two private methods: export class LayerEditor { public layerManager: LayerManager; constructor() { this.layerManager = new LayerManager(this); } private executeCommand() { ...

Implementing a soft transition to intl-tel-input plugin

This tel-input plugin was developed by Jack O'Connor. You can find the plugin here: https://github.com/Bluefieldscom/intl-tel-input I have observed that the flags take approximately one second to download, and I would like to enhance this process wi ...

Present information in a tabular format upon identifying an individual's ID using Angular

I encountered a specific issue recently. I successfully connected an API to my database using Angular, and it functions well by displaying all the data in a table. However, when I try to retrieve data for a single ID, the result can only be seen in an inpu ...

What steps are involved in switching the package manager for the Angular CLI, for example, replacing npm with pnpm when using `ng add`?

I couldn't find a lot of information on this topic, so I decided to ask a question on Stack Overflow. When it comes to commands like ng add @angular/material, I prefer using the package manager pnpm. ...

The rendering process in ag-grid is resulting in the service component initialized from an event to become null

Currently, I am utilizing ag-grid and need help understanding a specific issue. In my method for preparing GridOptions, I have set up an onCellValueChanged event that triggers a service component to access the database and populate the data. However, when ...

Tips for toggling visibility in Angular 2

I utilized [hidden] in the following way where the value of "secondTab" is set to true. <form #siteForm="ngForm" novalidate (ngSubmit)="saveSite(siteForm.value,siteForm.valid)" class="admin-modal"> <div class="txt-danger">{{errorMessage}}&l ...