Search code examples
angularcustom-elementcustom-tags

How to make custom tags with angular 2?


I have a problem with a custom component. The problem is that the link it with the model [(ngModule)] = "value" and gives an error is as follows:

Unhandled Promise rejection: Template parse errors:
Can't bind to 'ngModule' since it isn't a known property of 'gpi-input'.
1. If 'gpi-input' is an Angular component and it has 'ngModule' input, then verify that it is part of this module.
2. If 'gpi-input' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message.
("
<div>
    <h1>Input:</h1>
    <gpi-input name="someValue" [ERROR ->][(ngModule)]="valueInput">
        Escriu algu plis!!
    </gpi-input>

The code components are:

import { Component, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';

const noop = () => {
};

export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => GpiInputComponent),
    multi: true
};

@Component({
    selector: 'gpi-input',
    template: `<div class="form-group">
                    <label>
                        <ng-content></ng-content>
                    </label>
                    <input [(ngModel)]="value" class="form-control"         (blur)="onBlur()">
                </div>`,
    providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR],

})
export class GpiInputComponent implements ControlValueAccessor {

    //The internal data model
    private innerValue: any = '';

    //Placeholders for the callbacks which are later provided
    //by the Control Value Accessor
    private onTouchedCallback: () => void = noop;
    private onChangeCallback: (_: any) => void = noop;

    //get accessor
    get value(): any {
        return this.innerValue;
    };

    //set accessor including call the onchange callback
    set value(v: any) {
        if (v !== this.innerValue) {
            this.innerValue = v;
            this.onChangeCallback(v);
        }
    }

    //Set touched on blur
    onBlur() {
        this.onTouchedCallback();
    }

    //From ControlValueAccessor interface
    writeValue(value: any) {
        if (value !== this.innerValue) {
            this.innerValue = value;
        }
    }

    //From ControlValueAccessor interface
    registerOnChange(fn: any) {
        this.onChangeCallback = fn;
    }

    //From ControlValueAccessor interface
    registerOnTouched(fn: any) {
        this.onTouchedCallback = fn;
    }

}

And the app.module.ts

import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { NgbModule } from '@ng-bootstrap/ng-bootstrap';

import { AppComponent } from './app.component';
import { GpiInputComponent } from "../formularis/input/gpi-input";

@NgModule({
    imports: [BrowserModule, FormsModule, NgbModule.forRoot()],
    declarations: [AppComponent, GpiInputComponent],
    bootstrap: [AppComponent],
    schemas: [CUSTOM_ELEMENTS_SCHEMA]
})

export class AppModule { }

app.component:

import { Component } from '@angular/core';

import '../../public/css/styles.css';

@Component({
    selector: 'my-app',
    templateUrl: './src/app/app.component.html',
    //styleUrls: ['./app.component.css']
})
export class AppComponent {
    valueInput: string = "";
}

Can anyone dirme where the problem or give me a reference of what could be please. Thank you!! =)

Note:

I've seen other questions to the community CUSTOM_ELEMENTS_SCHEMA adds the file to app.module @NgModule within shcemas, but the problem persists.


Solution

  • The problem is not the component you are showing, but the component that uses that component.

    <gpi-input name="someValue" [ERROR ->][(ngModule)]="valueInput">
        Escriu algu plis!!
    </gpi-input>
    

    [(ngModule)] should be [(ngModel)]