Search code examples
angulartypescriptangular-directiveangular-componentsangular-module

Passing Data Between Two Components In Angular2 Produces Binding Error


I've been searching SO to resolve my issue, I know its been asked so many times but its no use for my problem.

I have two components:

  • departments

  • full-layout

The whole issue is trying to pass data from full-layout component to departments component using @Inputs().

Below I'll show you my folder structure first and then the code that I have.

The Structure

Department Folder Structure

Layout-Folder Structure

departments.component.ts

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

@Component({
  selector: 'app-departments',
  templateUrl: './departments.component.html',
  inputs: ['valueToPass']
})
export class DepartmentsComponent implements OnInit {
  @Input() valueToPass;
  public _departments;
  constructor () { }
  ngOnInit() {
    console.log(this.valueToPass.nam);
  }
}

departments.module.ts

// import{...}...
// assume necessary imports above

@NgModule({
  imports: [
    DepartmentsRoutingModule,
    CommonModule,
    MaterialModule.forRoot()
  ],
  declarations: [ DepartmentsComponent ]
})
export class DepartmentsModule {}

full-layout.component.ts

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

@Component({
  selector: 'app-dashboard',
  templateUrl: './full-layout.component.html',
})
export class FullLayoutComponent implements OnInit {
  public disabled:boolean = false;
  public status:{isopen:boolean} = {isopen: false};
  constructor (){}
  ngOnInit (): void {}


  dropDownItems = [
    { routerLink: '/departments',               name: 'Artshums' },
    { routerLink: '/components/social-buttons', name: 'Dentistry' },
    { routerLink: '/components/cards',          name: 'Law' },
    { routerLink: '/components/forms',          name: 'IOPPN' },
    { routerLink: '/components/modals',         name: 'LSM' },
    { routerLink: '/departments',               name: 'NMS' },
    { routerLink: '/components/tables',         name: 'Nursing' },
    { routerLink: '/components/tabs',           name: 'SSPP' },
    { routerLink: '/components/tabs',           name: 'Health' }
  ];

  onClick(_container: HTMLElement) {
    //this.clickedElement = _container.innerText;
    //console.log(this.clickedElement);
  }
}

full-layout.component.html

<ul class="nav-dropdown-items">
    <li class="nav-item" *ngFor="let item of dropDownItems">
        <a #clicked class="nav-link" routerLinkActive="active" [routerLink]="[item.routerLink]" (click)="onClick(clicked)">
            <i class="icon-puzzle"></i>{{item.name}}
            <app-departments [valueToPass] = "item"></app-departments>
        </a>
    </li>
</ul>

app.module.ts

// import {...}...
// assume necessary imports

@NgModule({
  imports: [
    BrowserModule,
    AppRoutingModule,
    DropdownModule.forRoot(),
    TabsModule.forRoot(),
    ChartsModule,
    MaterialModule.forRoot(),
    HttpModule,
    JsonpModule,
    DepartmentsModule
  ],
  declarations: [
    AppComponent,
    FullLayoutComponent,
    SimpleLayoutComponent,
    NAV_DROPDOWN_DIRECTIVES,
    BreadcrumbsComponent,
    SIDEBAR_TOGGLE_DIRECTIVES,
    AsideToggleDirective
  ],
  providers: [{
    provide: LocationStrategy,
    useClass: HashLocationStrategy
  }],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

My problem lies here. When I run this program, Im getting binding error, and Im not sure why and how to fix it.

Can't bind to 'valueToPass' since it isn't a known property of 'app-departments'.

  1. If 'app-departments' is an Angular component and it has 'valueToPass' input, then verify that it is part of this module.

  2. If 'app-departments' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message.

A small help would be highly appreciated it.

Thanks Champs!


Solution

  • When you use custom selectors like you are with this one: <app-departments>, you sometimes need to add "CUSTOM_ELEMENTS_SCHEMA" to '@NgModule.schemas' to avoid errors. By adding "CUSTOM_ELEMENTS_SCHEMA" to your module you're basically telling Angular to let you add custom elements to the app.

    So, in your root module, add this to the imports:

    import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
    

    And then, in that same root module, add "schemas" below "imports" as well, like this example:

    @NgModule({
        imports: [ RouterModule, CommonModule, FormsModule ],
        schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
    })
    

    Also, one note: it looks like you have a typo here - missing "e" in "name":

    console.log(this.valueToPass.nam);