2016-05-02 8 views
0

Ich versuche, Angular2 durch den Bau einer schönen Wysiwyg-Komponente zu lernen, aber es scheint, dass ich gerade eine Mauer schlagen. So, hier ist mein Code:Angular2 Wysiwyg Komponente nicht Beitrag

app.component.ts ist eine Form ich zum Testen der Komponente bin mit (i modifiziert, um die Helden Form von Winkel Tutorial):

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

und den HTML-Code für diese ist:

<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> 

und hier ist die wysıwyg Komponente:

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> 

editierbare-Bereich Komponente:

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

und html:

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

Der Rest des Projekts ist nur ein Haufen von Komponenten für die Symbolleiste. Nun, das Problem ist, dass, wenn ich das Formular einreiche, bekomme ich nichts von der Wysiwyg, sogar doe ich Inhalt darin zu schreiben, und ich sehe, dass Inhalt in die textarea kopiert wird, es nicht mit dem Rest des Formulars posten. Ich habe die Konsole überprüft und es gibt keine Ausnahmen, alles sieht gut aus. Kann jemand sehen, was ich falsch mache? Vielen Dank.

+1

Sie benötigen ein 'ControlValueAccessor', damit benutzerdefinierte Elemente funktionieren können w its 'ngModel' http://stackoverflow.com/search?q=%5Bangular2%5D+controlvalueaccessor –

Antwort

1

Es gibt zwei Dinge hier.

Wenn Sie Zwei-Wege-Bindung nutzen möchten, müssen Sie auch eine Output in Ihrer Komponente haben:

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

Außerdem Ihre aEditable Komponente ngModel/ngControl konform. Dies bedeutet, dass er nicht an der Formularvalidierung und seinem globalen Status teilnehmen kann. Wenn Sie diese Funktion benötigen/benötigen, müssen Sie einen benutzerdefinierten Werteaccessor implementieren. Hier ist ein Beispiel, in Ihrem Fall:

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

beenden Sie Angular2 Unterstützung nutzen könnten mit dem DOM zu interagieren, anstatt jQuery verwenden. Zum Beispiel mit dem @ViewChild Dekorateur:

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

Und in der Komponente

@ViewChild('editable') 
editableElement:ElementRef; 

@ViewChild('editableArea') 
editableAreaElement:ElementRef; 

constructor(private renderer:Renderer) { 
} 

onAfterViewInit() { 
    (...) 
} 

Diese Frage editierbare Inhalt in Bezug könnten Sie auch interessieren:

Verwandte Themen