2016-05-02 70 views
0

我正在嘗試通過構建一個不錯的wysiwyg組件來學習angular2,但它現在接觸了我打磚牆。所以,這裏是我的代碼:Angular2 wysiwyg組件無法發佈

app.component.ts是我使用的用於測試部件的形式(修改從角教程中的英雄式):

import {Component} from 'angular2/core'; 
import {NgForm} from 'angular2/common'; 
import { Article } from './article'; 
import {aWysiwygComponent} from './aWysiwyg.component' 

@Component({ 
    selector: 'test-form', 
    templateUrl: 'app/article-form.component.html', 
    directives: [aWysiwygComponent] 
}) 
export class ArticleFormComponent { 
    model = new Article(18, 'Dr IQ', 'Chuck Overstreet'); 
    submitted = false; 
    onSubmit() { this.submitted = true; } 
    // Reset the form with a new hero AND restore 'pristine' class state 
    // by toggling 'active' flag which causes the form 
    // to be removed/re-added in a tick via NgIf 
    // TODO: Workaround until NgForm has a reset method (#6822) 
    active = true; 
    newArticle() { 
    this.model = new Article(42, '', ''); 
    this.active = false; 
    setTimeout(()=> this.active=true, 0); 
    } 
} 

,爲此在html是:

<div class="container"> 
    <div [hidden]="submitted"> 
    <h1>Hero Form</h1> 
    <form *ngIf="active" (ngSubmit)="onSubmit()" #articleForm="ngForm"> 
     <div class="form-group"> 
     <label for="name">Name</label> 
     <input type="text" class="form-control" required 
      [(ngModel)]="model.name" 
      ngControl="name" #name="ngForm" > 
     <div [hidden]="name.valid || name.pristine" class="alert alert-danger"> 
      Name is required 
     </div> 
     </div> 
     <div class="form-group"> 
      <label for="content">Content</label> 
      <aWysiwyg [(model)]="model.content"></aWysiwyg> 
     </div> 
     <button type="submit" class="btn btn-default" [disabled]="!articleForm.form.valid">Submit</button> 
     <button type="button" class="btn btn-default" (click)="newArticle()">New Article</button> 
    </form> 
    </div> 
    <div [hidden]="!submitted"> 
    <h2>You submitted the following:</h2> 
    <div class="row"> 
     <div class="col-xs-3">Name</div> 
     <div class="col-xs-9 pull-left">{{ model.name }}</div> 
    </div> 
    <div class="row"> 
     <div class="col-xs-3">Content</div> 
     <div class="col-xs-9 pull-left">{{ model.content }}</div> 
    </div> 
    <br> 
    <button class="btn btn-default" (click)="submitted=false">Edit</button> 
    </div> 
</div> 

,這裏是所見即所得的組件:

import {Component, ViewEncapsulation, Input} from 'angular2/core'; 
import {ToolbarComponent} from './components/toolbar.component'; 
import {EditableComponent} from './components/editable.component'; 
import { NgForm, FORM_PROVIDERS, FORM_DIRECTIVES } from 'angular2/common'; 


@Component({ 
    selector: 'aWysiwyg', 
    templateUrl: '../app/templates/editor.html', 
    styleUrls:['./app/styles/bootstrap.min.css', './app/styles/styles.css', './app/styles/font-awesome.min.css'], 
    encapsulation: ViewEncapsulation.None, 
    providers: [FORM_PROVIDERS], 
    directives: [ToolbarComponent, EditableComponent, FORM_DIRECTIVES] 
}) 
export class aWysiwygComponent { 
    @Input() model:any; 
} 

HTML:

<section class="editor col-sm-24 col-lg-24"> 
    <aToolbar class="row">Loading...</aToolbar> 
    <aEditable [(model)]="model" class="row">Loading...</aEditable> 
</section> 
<textarea class="form-control" id="hiddenInput" hidden>{{model}}</textarea> 

可編輯區域組成:

import {Component, Input, AfterViewInit} from 'angular2/core'; 
import { NgForm, FORM_PROVIDERS, FORM_DIRECTIVES } from 'angular2/common'; 

@Component({ 
    selector: 'aEditable', 
    templateUrl: './app/templates/editable.html', 
    providers: [FORM_PROVIDERS], 
    directives: [FORM_DIRECTIVES] 
}) 
export class EditableComponent implements AfterViewInit { 
    @Input() model:any; 

    ngAfterViewInit(){ 
     jQuery('#editable-area').keyup(function(){ 
      jQuery('#hiddenInput').text(jQuery('#editable-area').html()) 
     }) 
    } 
} 

和HTML:

<section id="editable"> 
    <div id="editable-area" contenteditable > 
     {{model}} 
    </div> 
</section> 

項目剩下的只是一堆的工具欄組件。現在,問題是,當我提交表單時,我從wysiwyg中得不到任何東西,即使是我正在寫內容,並且我看到內容被複制到textarea,它不會將其與表單的其餘部分一起發佈。我檢查了控制檯,沒有任何例外,一切看起來都很好。任何人都可以看到我做錯了什麼?謝謝。

+1

你需要一個'ControlValueAccessor'自定義元素工作w ith'ngModel' http://stackoverflow.com/search?q=%5Bangular2%5D+controlvalueaccessor –

回答

1

這裏有兩件事。

如果你想利用雙向綁定,你還需要在你的組件的Output

@Component({ 
    selector: 'aEditable', 
    templateUrl: './app/templates/editable.html', 
    providers: [FORM_PROVIDERS], 
    directives: [FORM_DIRECTIVES] 
}) 
export class EditableComponent implements AfterViewInit { 
    @Input() model:any; 
    // The name is important here (the suffix "Change") to be 
    // able to use the syntax shortcut: [(model)] 
    @Output() modelChange:EventEmitter<any> = new EventEmitter(); 

    ngAfterViewInit(){ 
    jQuery('#editable-area').keyup(() => { 
     let content = jQuery('#editable-area').html(); 
     this.modelChange.emit(content); 
     jQuery('#hiddenInput').text(content); 
    }); 
    } 
} 

此外,您aEditable成分是ngModel/ngControl兼容。這意味着它不能參與表單驗證及其全局狀態。如果你想/需要這個功能,你必須實現一個自定義值訪問器。這是你的情況的例子:

const EDITABLE_VALUE_ACCESSOR = new Provider(NG_VALUE_ACCESSOR, { useExisting: forwardRef(() => EditableComponent), multi: true}); 

@Component({ 
    selector: 'aEditable', 
    templateUrl: './app/templates/editable.html', 
    providers: [FORM_PROVIDERS, EDITABLE_VALUE_ACCESSOR], 
    directives: [FORM_DIRECTIVES] 
}) 
export class EditableComponent implements ControlValueAccessor { 
    content:string; 

    onChange = (_) => {}; 
    onTouched =() => {}; 

    writeValue(value: any): void { 
    this.content = value; 
    // write in the DOM 
    } 

    ngAfterViewInit(){ 
    jQuery('#editable-area').keyup(() => { 
     this.content = jQuery('#editable-area').html(); 
     jQuery('#hiddenInput').text(this.content); 
     this.onChange(content); 
    }); 
    } 

    registerOnChange(fn: (_: any) => void): void { this.onChange = fn; } 
    registerOnTouched(fn:() => void): void { this.onTouched = fn; } 
} 

才能完成,你可以利用Angular2支持與DOM的,而不是使用jQuery交互。例如與@ViewChild裝飾:

<section #editable> 
    <div id=#editableArea contenteditable > 
    {{model}} 
    </div> 
</section> 

而在組件

@ViewChild('editable') 
editableElement:ElementRef; 

@ViewChild('editableArea') 
editableAreaElement:ElementRef; 

constructor(private renderer:Renderer) { 
} 

onAfterViewInit() { 
    (...) 
} 

關於編輯的內容這個問題也可能感興趣: