Reputation: 53
Let's say I have a textarea, inside which are some substrings that match pattern. Is there a way I can edit that substring through text input.
Example: I have a textArea that contains next string:
${1:scan1}
${2:scan2}
${3:scan3}
I am subscribing to valueChanges of it and calling regex to get all repetitions of that string and converting them to FormControl, than pushing it to FormArray, so value pushed through FormControl is only text inside ( ${scan1} -> scan1 )
<textarea cols="30" rows="10" [formControl]="textArea"></textarea>
export class AppComponent implements OnInit {
textArea: FormControl = new FormControl("");
detectedStrings: FormArray = new FormArray([]);
constructor() {}
ngOnInit() {
this.textArea.valueChanges.subscribe((textBodyText: string) => {
const foundStrings =
textBodyText.match(/[$][{][1-9][0-9]*[:][a-zA-Z0-9 ]{0,}[}]/g) || [];
this.detectedStrings.clear();
foundStrings.map(_string => {
this.detectedStrings.push(
new FormControl(
_string.substring(_string.indexOf(":") + 1, _string.indexOf("}"))
)
);
});
});
}
}
Then I'm displaying all found scans in list as input:
<div [formGroup]="detectedStrings">
<div *ngFor="let string of detectedStrings.controls; let i = index">
<input type="text" [formControlName]="i" />
</div>
</div>
Now what I want is that as I would edit text in input, text in textarea would also change dynamically. ( scan1 -> scan100 )
Note: This is just a recreation
Upvotes: 1
Views: 1715
Reputation: 4117
I have followed following steps,
keyup
event, get the respective start index of tag from step 1FormArray
control to existing value of TextArea
TextArea
.Demo Stackblitz
Typescript
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
name = "Angular";
textArea: FormControl = new FormControl("");
formArray: FormArray;
tags: any;
// array to hold prev changes, which is used to avoid stack size exceeded error
// as this is cyclic behaviour
formArrayChanges: string[] = [];
constructor() {
this.formArray = new FormArray([]);
}
ngOnInit() {
this.textArea.valueChanges.subscribe((textBodyText: string) => {
const regex = /[$][{][1-9][0-9]*[:][a-zA-Z0-9 ]{0,}[}]/g;
const foundStrings = textBodyText.match(regex) || [];
this.tags = new Object();
let match;
while ((match = regex.exec(textBodyText)) != null) {
this.tags[match.index] = match[0];
}
// clear saved array
this.formArray.clear();
foundStrings.map(str => {
// get id and value of control
let id = str.substring(2, str.indexOf(":"));
let value = str.substring(str.indexOf(":") + 1, str.indexOf("}"));
this.formArray.push(new FormControl(value));
});
});
this.textArea.setValue("${1:scan1}\n${1:scan1}\n${2:scan2}\n${3:scan3}");
}
onControlKey(index: number) {
let currTextAreaValue = this.textArea.value;
const tagStartIndex = Object.keys(this.tags)[index];
console.log(tagStartIndex, this.tags[tagStartIndex]);
const valueStartIndex = currTextAreaValue.indexOf(":", tagStartIndex) + 1; // +1 to remove :
let valueEndIndex = currTextAreaValue.indexOf("}", valueStartIndex);
currTextAreaValue =
currTextAreaValue.substring(0, valueStartIndex) +
this.formArray.at(index).value +
currTextAreaValue.substring(valueEndIndex);
this.textArea.setValue(currTextAreaValue);
}
}
Template
<textarea cols="30" rows="10" [formControl]="textArea"></textarea>
<hr>
<div [formGroup]="formArray">
<div *ngFor="let string of formArray.controls; let i = index">
<input type="text" [formControlName]="i" (keyup)="onControlKey(i)"/>
</div>
</div>
Upvotes: 1
Reputation: 856
I hope my code helps to you.
Step 1. Add event(keyup) to your template.
<textarea cols="30" rows="10" [formControl]="textArea"></textarea>
<div [formGroup]="detectedStrings">
<div *ngFor="let string of detectedStrings.controls; let i = index">
<input #box type="text" [formControlName]="i" (keyup)="onKey($event, i)" />
</div>
</div>
Step 2. Handle event and update textarea.
onKey(event: any, index: any) {
console.log(index + ' changed: ' + event.target.value);
this.textArea.setValue('${1:scan1}\n${2:scan2}\n${3:scan33}'); //This is one of sample.
}
I think it is hard part to update original text at textArea
.
But you may know what is requirement, so you can make.
Here is my sample code.
Upvotes: 0