Angular 8: ERROR in Can't resolve all parameters for TextAreaEditorComponent

Viewed 118

We recently upgraded angular to 8.2.14 The below code was a class which i attempted to convert to a component. I get the following error

ERROR in Can't resolve all parameters for TextAreaEditorComponent

Basically the issue is the constructor .

This was to extend a vendor app SpreadJS

 import { Component, OnInit, ElementRef, ViewChild, Input, Optional } from '@angular/core';


@Component({
    styleUrls: ['./text-area-editor.component.scss'],
    templateUrl: './text-area-editor.component.html'
})
export class TextAreaEditorComponent implements OnInit {
   // @Input() options: any;
    options: any;
    textArea: any;
    containerKeyDownHandler: any;
    containerClickHandler: any;
    maxLength = 500;

    @ViewChild('container', { static: true }) input: ElementRef;

    constructor(
       options: any
    ) {
      this.options = options;
    }

    ngOnInit() {
    }

    init(): void {
        const options = this.options;
        const container = options.container;
        this.maxLength = this.options.col.editor.maxLength;

        this.textArea = container.children[0];

        this.textArea.value = options.value;
        this.textArea.focus();

        this.handleClick = this.handleClick.bind(this);
        this.handleKeyDown = this.handleKeyDown.bind(this);

        container.addEventListener('click', this.handleClick);
        container.addEventListener('keydown', this.handleKeyDown);
    }

    destroy() {
        const container = this.options.container;
        container.removeEventListener('click', this.handleClick);
        container.removeEventListener('keydown', this.handleKeyDown);
    }

    focus() {
        this.textArea.focus();
    }

    serialize() {
        return this.textArea.value;
    }

    handleClick(event) {
        event.stopPropagation();
        if (event.target && event.target.tagName.toLowerCase() === 'button') {
            if (event.target.className === 'save') {
                this.options.dataview.stopEditing();
            } else if (event.target.className === 'cancel') {
                this.options.dataview.cancelEditing();
            }
        }
    }

    handleKeyDown(event) {
        if (event.defaultPrevented || !document.activeElement) {
            return;
        }


        if (event.srcElement.value.length > this.maxLength) {
            event.srcElement.value = event.srcElement.value.substring(0, this.maxLength);

        }
        const key = event.key || event.keyCode;
        if (key === 'Enter' || key === 13) {
            if (document.activeElement.className === 'save') {
                event.stopPropagation();
                this.options.dataview.stopEditing();
            } else if (document.activeElement.className === 'cancel') {
                event.stopPropagation();
                this.options.dataview.cancelEditing();
            }
        }
    }
}
2 Answers

As it is pointed out by Kurt Hamilton in the comments, a component's initialization is handled by Angular's injection system unless you do it explicitly. So, Angular has to know what options is. You can simply show Angular what needs to be used as options:

in your app.module.ts provide the options object by specifying it's value

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...
  ],
  providers: [
  {provide: 'myoptions', useValue: {a: 'some option', b: 'some other option'}}],
  bootstrap: [AppComponent]
})

Inject the options with the injection key you specified.

  constructor(@Inject('myoptions') options) {

  }

This is actually what you do if you need to have access to that same options object throughout the module or application. However if the options will change for each different TextAreaComponent you have, then you should pass it as an @Input. That way you will be able to change the options dynamically.

You can find the instructions for @Input at angular.io: https://angular.io/guide/component-interaction#pass-data-from-parent-to-child-with-input-binding

In TextAreaComponent Decorator selector for this component is missing. There should be a selector for the component.

Related