How can I use ngControl in contenteditable element?

烂漫一生 提交于 2019-12-23 18:50:31

问题


How can I use ngControl in contenteditable element? For example, I want:

<!-- *ngFor over rows and columns in table -->
<td contenteditable="true" [ngControl]="row.number + column.number"></td>

With binding (?) it to model-driven "form" (table). I create him with formBuilder based on schema, that retrieve from server.
Currently I think that doesnt work, 'cause <td> (and others) element haven't property value. Then, possible to overload some methods to work with textContent property? Or exist other way to do this?

Thank you.


回答1:


To be able to use contenteditable elements with Angular2 and controls, you need to create a custom directive that applies to the contenteditable This directive must be ngModel / ngForm compatible so you will be able to use directives like ngForm and ngFormControl. Internally this directive will register a custom `Value

Here is a possible implementation:

const CUSTOM_VALUE_ACCESSOR = CONST_EXPR(new Provider(
  NG_VALUE_ACCESSOR, {useExisting: forwardRef(() => ContenteditableAccessor), multi: true}));

@Directive({
  selector: '[contenteditable]',
  host: {'(blur)': 'onBlur($event)'},
  providers: [CUSTOM_VALUE_ACCESSOR]
})
export class ContenteditableAccessor implements ControlValueAccessor {
  onChange = (_) => {};
  onTouched = () => {};

  constructor(private eltRef:ElementRef) {
  }

  ngOnInit() {
    this.onChange(this.eltRef.nativeElement.innerText);
  }

  writeValue(value: any): void {
    if (value!=null) {
      this.eltRef.nativeElement.innerText = value;
    }
  }

  onBlur(event) {
    this.onChange(this.eltRef.nativeElement.innerText);
  }

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

You will be able to use this directive this way in a component:

@Component({
  selector: 'my-app',
  template: `
    <div>
      <form>
        <label>First name:</label>
        <span contenteditable="true" [ngFormControl]="testCtrl">Some value</span>
      </form>
      <div>
        firstName: {{testCtrl.value}}<br/>
        firstName: {{testCtrl.valid}}<br/>
      </div>
      <div (click)="updateConditions()">Update conditions</div>
    </div>
  `,
  directives: [ FORM_DIRECTIVES, ContenteditableAccessor ]
})
export class AppComponent {
  constructor() {
    this.testCtrl = new Control();
  }
}

Here is the corresponding plunkr: https://plnkr.co/edit/JbjXIa?p=preview.

For more details about ngForm / ngModel compliant custom components, you could have a look at this article in the section "NgModel-compatible component":

  • http://restlet.com/blog/2016/02/17/implementing-angular2-forms-beyond-basics-part-2/


来源:https://stackoverflow.com/questions/36122136/how-can-i-use-ngcontrol-in-contenteditable-element

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!