2015-12-02 94 views
2

我遇到動態添加的CKEditors問題,通過NgFor[email protected]Angular2和動態添加的CKEditors中斷

Live demo is available here.

@Directive({ 
    selector: 'textarea' 
}) 
class CKEditor { 
    constructor(_elm: ElementRef) { 
     CKEDITOR.replace(_elm.nativeElement); 
    } 
} 

@Component({ 
    selector: 'my-app', 
}) 
@View({ 
    directives: [NgFor, CKEditor], 
    template: ` 
     <div *ng-for="#item of items"> 
     {{ item }}: <textarea>{{ item }}</textarea> 
     </div> 
     <button (click)="addItem()">Add</button>` 
}) 
class AppComponent { 
    items = ['default_0', 'default_1']; 

    constructor() { 
     this.addItem(); 
    } 

    addItem() { 
     var id = 'ckeditor_inst_' + this.items.length; 
     this.items.push(id); 
    } 
} 

你可以看到,正常工作3個CKEditors。然後點擊底部的「添加」按鈕,打開容器中的最後一個CKEditor,甚至可以寫入它,如果按下任何工具欄按鈕,它會拋出:

Uncaught TypeError: Cannot read property 'getSelection' of undefined

有趣的是,只有最後一個CKEditor被破壞,另外兩個工作。看起來Angular2不知何故地操縱了打破CKEditor的最後一個元素。

我記得使用在[email protected]中添加新的CKEditors的相同方式,我認爲它在那裏工作,但也許我只是沒有注意到。版本[email protected] is the same

回答

4

您的集成使用Classic CKEditor,因爲wysiwygarea插件允許在中進行編輯(即避免CSS與網頁衝突)。

這種實現的缺點是,一旦從DOM(如Angular每次添加一個新的item)分離(並重新附加),其內部document就會「斷開」。我的意思是,document.body是從頭開始加載的,失去了你的內容,CKEditor引導代碼,JS引用等等,最終導致整個編輯器實例無用。

所以,問題就出在這個視圖所呈現的方式:

@View({ 
    directives: [NgFor, CKEditor], 
    template: ` 
     <div *ng-for="#item of items"> 
     {{ item }}: <textarea>{{ item }}</textarea> 
     </div> 
     <button (click)="addItem()">Add</button>` 
}) 

而且我看到三個解決問題的對策:

  • 乾淨的解決方案:強制角不重新渲染當添加新項目時,整個items集合。
  • 棘手的解決方案:使用Inline CKEditor,其工作在<div contenteditable="true" /> div而不是<iframe>...<body contenteditable="true" /></iframe>,並且對DOM中的突變免疫。
  • 懶惰和緩慢的解決方案:堅持目前的集成,但銷燬所有CKEDITOR.instancesinstance.destroy())之前添加一個新的項目,然後重新初始化他們CKEDITOR.replace()