Angular2 wysiwyg组件未发布



我正试图通过构建一个漂亮的wysiwyg组件来学习angular2,但它的接缝让我现在碰壁了。所以,这是我的代码:

app.component.ts是我用来测试组件的一个表单(我从angular教程中修改了英雄表单):

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>

这是wysiwyg组件:

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中,它也不会将其与表单的其他部分一起发布。我检查了控制台,没有任何异常,一切看起来都很好。有人看到我做错了什么吗?非常感谢。

这里有两件事。

如果你想利用双向绑定,你还需要在你的组件中有一个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() {
  (...)
}

这个关于可编辑内容的问题也可能引起你的兴趣:

  • 如何在contenteditable元素中使用ngControl

最新更新