Angular 2 contenteditable div,将插入符号移到最终位置

时间:2017-05-05 12:55:49

标签: html angular

我有以下Angular 2代码:

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:

从'./../../services/service/validator.service'导入{ValidatorService};    从'@ angular / core'导入{Directive,HostListener,Input,ElementRef,OnInit,SimpleChanges,EventEmitter,Output};

@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);
    }
 }

我想动态更新一个有意义的div,请参阅write.component.html,它链接到由指令contenteditable.directive.ts管理的模型。类变量writeText被发送到指令以检查用户是否已写入url,如果是这种情况,则url内容应转换为:url。这在div中呈现为html:

enter image description here

enter image description here

问题是,每当我键入一些文本时,插入符/光标总是会跳转 到开始位置:

enter image description here

是否可以手动将光标移动到div内容的末尾? 内容可以是文本和HTML。 我试过这里提出的解决方案没有运气:

Set the caret position always to end in contenteditable div

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

enter image description here 在我的问题中,我在输入时触发焦点(它自动转到新行)并重新聚焦(到最后一个todo的最后一个字符)如果我删除

....
 // 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);
  }

注意“el.lastChild”,你的contenteditable使用(textContent或innerHTML?)

答案 1 :(得分:1)

我希望你仍然有兴趣得到答案。我能想象的最简单的方法是保存对<a>节点的引用并使用它来放置插入符号。

ContenteditableModel内,您只需创建以下内容:

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);
}

这允许您使用elRef将插入符号放在其最后一个子节点<a>元素的最后一个字符处。