Reputation: 247
I have following Angular 2 code:
write.component.ts:
import { CommentHeaderComponent } from './comment.header.component';
import { StyleService } from './../../services/services/style.service';
import { Parameters } from './../../services/services/parameters';
import { Component, Input, ViewChild,ElementRef,HostBinding} from "@angular/core";
import { ContenteditableModel } from './../directives/contenteditable.directive';
@Component({
selector:'write',
templateUrl:'app/templates/write.component.html',
styleUrls:['app/templates/css/write.component.css']
})
export class WriteComponent
{
@HostBinding('class.hbox')
parameters:Parameters;
private writeText:string="";
private rows:number=1;
private maxRows:number=4;
private comment:boolean=false;
private lineHeight:string="1.7em";
@ViewChild('writeBox') writeBox:ElementRef;
constructor(private stService:StyleService){}
ngOnInit()
{
this.writeBox.nativeElement.innerText="";
this.stService.setProperty(this.writeBox,[{rows:this.rows}]);
this.stService.setStyle(this.writeBox,[{lineHeight:this.lineHeight}]);
if (this.parameters.Iskey("comment"))
{
this.comment=true;
}
}
write(data:any)
{
this.parameters.cfunc({event:"comment",message : this.writeText});
this.writeText="";
}
getWriteText():String
{
return this.writeText;
}
}
write.component.html:
<div contenteditable="true" #writeBox [ceModel]="writeText" (ceChange)="writeText=$event" [innerHTML]="writeText">
</div>
<ng-template [ngIf]="this.comment">
<button type="button" (click)="files($event)" class="btn fa fa-paperclip"> </button>
</ng-template>
<button type="button" (click)="write($event)" class="btn fa fa-chevron-right"> </button>
contenteditable.directive.ts:
import { ValidatorService } from './../../services/service/validator.service'; import { Directive, HostListener, Input, ElementRef, OnInit, SimpleChanges, EventEmitter, Output } from '@angular/core';
@Directive({selector: '[ceModel]'})
export class ContenteditableModel
{
@Input('ceModel') ceModel: any="";
@Output('ceChange') ceChange = new EventEmitter();
constructor(private elRef: ElementRef,private v:ValidatorService) {}
@HostListener('keyup', ['$event'])
onChange($event: any)
{
if ($event.keyCode==32)
{
console.log(this.ceModel);
this.ceModel="<a>"+this.ceModel+"<\a>";
this.ceChange.emit(this.ceModel);
return;
}
this.ceModel=this.elRef.nativeElement.innerText;
this.ceChange.emit(this.ceModel);
}
@HostListener('paste', ['$event'])
onPaste($event: any)
{
console.log($event);
}
}
I want to update dynamically a contenteditable div, see write.component.html, that is linked to a model that is managed by a directive,contenteditable.directive.ts. The class variable writeText is sent to the directive in order to check whether a user has written a url, if this is the case, the url content should be transformed to: url. This is rendered in the div as html:
The problem is, that whenever I type some text, the caret/cursor jumps always to the start position:
Is it possible to manually move the cursor to end of the div content? The content may be text and html. I have tried the solutions proposed here with no luck:
Set the caret position always to end in contenteditable div
Thank you for your help.
Upvotes: 1
Views: 4093
Reputation: 4093
in my problem, I trigger focus when enter (it auto go to new line) and refocus (to the last character of last todo) if i delete
....
// somewhere you trigger that focus event:
(div:HTMLElement) => {
// div.focus();
if (div.lastChild) this.setSelectionRange(div)
else div.focus();
this.changeDetector.detectChanges();
}
....
setSelectionRange(el:HTMLElement) {
let range = document.createRange();
let pos = el.lastChild.textContent.length;
let sel = window.getSelection();
console.log('el last child',el.lastChild.textContent.length,typeof(el.lastChild.textContent.length));
range.setStart(el.lastChild, pos);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
notice at "el.lastChild", your contenteditable using (textContent or innerHTML?)
Upvotes: 2
Reputation: 528
I hope you're still interested in getting an answer to this. The easiest approach I can imagine is to save a reference to the <a>
node and use it to place the caret.
Inside ContenteditableModel
you simply can create the following:
private moveCaret(): void {
let range = document.createRange(),
pos = this.elRef.lastChild.innerText.length - 1,
sel = window.getSelection();
range.setStart(this.elRef, pos);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
This allows you to use your elRef to place the caret at the last char of its last child, the <a>
element.
Upvotes: 1