Can't have event on ng-template? Event binding click not emitted by any directive on an embedded template

imnickvaughn picture imnickvaughn · Jun 3, 2018 · Viewed 15.3k times · Source

I am trying to simply use *ngIf ;else to render a button or not but keep getting this error. It seems I can not have an event on my ng-template? This can't be so. I must be doing something obviously wrong.

The event name (click) is obviously spelled correctly and from what I know all directives I need Browser and Common modules are imported and listed in the NgModule metadata.

Error:

Event binding click not emitted by any directive on an embedded template. Make sure that the event name is spelled correctly and all directives are listed in the "@NgModule.declarations".

This is the only real solution I found for this problem: Solution 1 but I have BrowserModule and CommonModule both imported into AppModule and the module closest to where the error is occurring.

Event binding click not emitted by any directive on an embedded template. Make sure that the event name is spelled correctly and all directives are listed in the "@NgModule.declarations".

Very close to just using two *ngIfs (which works fyi)... why can't I have an event on my ng-template? I've replaced the changeViewState() with a property and changed the (click) event to an (activate) and (mouseover) event... It seems to not like any (event) on the ng-template...

I've copy-pasted the problem code around my application and it errors each time.

'problem code':

<div *ngIf="(this.stateUserReqValid === 'userInfo' || this.stateUserReqValid === 'orgInfo' || this.stateUserReqValid === 'supInfo' || this.stateUserReqValid === 'secInfo'); else ele"
  class="userManHover" (click)="changeViewState('userInfo');" [ngClass]="{'userManSelect': stateUserReq =='userInfo'}">
  <h4 class="font-weight-light">
    <span class="blade-2-number" [ngClass]="{'blade-2-activated-number' :  stateUserReq =='userInfo'}">1 </span> User Information &nbsp;
    <span class="icon-accept user-man-accept"></span>
  </h4>
</div>
<ng-template #ele class="userManHover" (click)="changeViewState('userInfo')" [ngClass]="{'userManSelect': stateUserReq =='userInfo'}">
  <h4 class="font-weight-light">
    <span class="blade-2-number" [ngClass]="{'blade-2-activated-number' :  stateUserReq =='userInfo'}">1 </span> User Information &nbsp;
    <span class="icon-accept user-man-accept"></span>
  </h4>
</ng-template>



new-user.component.html

<!-- <app-page-header [icon]="'fa fa-users'"></app-page-header> -->
<!-- <app-page-header [heading]="'User Management'" [icon]="'fa fa-users'"></app-page-header> -->



<!-- BLADE LAYER 1 -->
<div class="blade" [@routerTransition]>
  <div class="blade-header">
    <!-- <div class="blade-header" [ngClass]="{'is-minimized-header':minimizeVar}"> -->
    <h3>NEW USER REQUEST</h3>
  </div>


  <!-- [ngClass]="{'feature-nav-button': portalState =='portal-a', 'click-portal-style': portalState =='portal-a'}" -->

  <!-- BLADE Contents -->
  <div class="blade-contents">

    <!-- <div *ngIf="((this.stateUserReqValid != 'userInfo') || (this.stateUserReqValid != 'orgInfo') || (this.stateUserReqValid != 'supInfo') || (this.stateUserReqValid != 'secInfo'))" class="userManHover" (click)="changeViewState('userInfo');" [ngClass]="{'userManSelect': stateUserReq =='userInfo'}">
      <h4 class="font-weight-light">
        <span class="blade-2-number" [ngClass]="{'blade-2-activated-number' :  stateUserReq =='userInfo'}">1 </span> User Information &nbsp;
        <span class="icon-right user-man-chevron"></span>
      </h4>
    </div> -->

    <div *ngIf="(this.stateUserReqValid === 'userInfo' || this.stateUserReqValid === 'orgInfo' || this.stateUserReqValid === 'supInfo' || this.stateUserReqValid === 'secInfo'); else ele"
      class="userManHover" (click)="changeViewState('userInfo');" [ngClass]="{'userManSelect': stateUserReq =='userInfo'}">
      <h4 class="font-weight-light">
        <span class="blade-2-number" [ngClass]="{'blade-2-activated-number' :  stateUserReq =='userInfo'}">1 </span> User Information &nbsp;
        <span class="icon-accept user-man-accept"></span>
      </h4>
    </div>
    <ng-template #ele class="userManHover" (click)="changeViewState('userInfo')" [ngClass]="{'userManSelect': stateUserReq =='userInfo'}">
      <h4 class="font-weight-light">
        <span class="blade-2-number" [ngClass]="{'blade-2-activated-number' :  stateUserReq =='userInfo'}">1 </span> User Information &nbsp;
        <span class="icon-accept user-man-accept"></span>
      </h4>
    </ng-template>


    <div *ngIf="this.stateUserReqValid != 'orgInfo'" class="userManHover" [ngClass]="{'userManSelect': stateUserReq =='orgInfo'}">
      <h4 class="font-weight-light">
        <span class="blade-2-number" [ngClass]="{'blade-2-activated-number' :  stateUserReq =='orgInfo'}">2 </span> Organization &nbsp;
        <span class="icon-right user-man-chevron"></span>
      </h4>
    </div>
    <!-- <div *ngIf="this.stateUserReqValid === 'userInfo' || this.stateUserReqValid === 'orgInfo' || this.stateUserReqValid === 'supInfo' || this.stateUserReqValid === 'secInfo'" class="userManHover" (click)="changeViewState('orgInfo');" [ngClass]="{'userManSelect': stateUserReq =='orgInfo'}"> -->
    <div *ngIf="this.stateUserReqValid === 'orgInfo'" class="userManHover" (click)="changeViewState('orgInfo');" [ngClass]="{'userManSelect': stateUserReq =='orgInfo'}">
      <h4 class="font-weight-light">
        <span class="blade-2-number" [ngClass]="{'blade-2-activated-number' :  stateUserReq =='orgInfo'}">2 </span> Organization &nbsp;
        <span class="icon-accept user-man-accept"></span>
      </h4>
    </div>


    <div *ngIf="this.stateUserReqValid != 'userInfo' || this.stateUserReqValid != 'orgInfo' || this.stateUserReqValid != 'supInfo' || this.stateUserReqValid != 'secInfo'"
      class="userManHover" [ngClass]="{'userManSelect': stateUserReq =='supInfo'}">
      <h4 class="font-weight-light">
        <span class="blade-2-number" [ngClass]="{'blade-2-activated-number' :  stateUserReq =='supInfo'}">3 </span> Supervisor &nbsp;
        <span class="icon-right user-man-chevron"></span>
      </h4>
    </div>
    <div *ngIf="this.stateUserReqValid === 'supInfo'" class="userManHover" (click)="changeViewState('supInfo');" [ngClass]="{'userManSelect': stateUserReq =='supInfo'}">
      <h4 class="font-weight-light">
        <span class="blade-2-number" [ngClass]="{'blade-2-activated-number' :  stateUserReq =='supInfo'}">3 </span> Supervisor &nbsp;
        <span class="icon-right user-man-chevron"></span>
      </h4>
    </div>

    <div *ngIf="this.stateUserReqValid != 'secInfo'" class="userManHover" [ngClass]="{'userManSelect': stateUserReq =='secInfo'}">
      <h4 class="font-weight-light">
        <span class="blade-2-number" [ngClass]="{'blade-2-activated-number' :  stateUserReq =='secInfo'}">4 </span> Security Profiles &nbsp;
        <span class="icon-right user-man-chevron"></span>
      </h4>
    </div>
    <div *ngIf="this.stateUserReqValid === 'secInfo'" class="userManHover" (click)="changeViewState('secInfo');" [ngClass]="{'userManSelect': stateUserReq =='secInfo'}">
      <h4 class="font-weight-light">
        <span class="blade-2-number" [ngClass]="{'blade-2-activated-number' :  stateUserReq =='secInfo'}">4 </span> Security Profiles &nbsp;
        <span class="icon-right user-man-chevron"></span>
      </h4>
    </div>
  </div>
</div>

<div *ngIf="stateUserReq === 'userInfo'">
  <new-user-req></new-user-req>
</div>
<div *ngIf="stateUserReq === 'orgInfo'">
  <new-user-org-info></new-user-org-info>
</div>
<div *ngIf="stateUserReq === 'supInfo'">
  <new-user-supervisor-info></new-user-supervisor-info>
</div>
<div *ngIf="stateUserReq === 'secInfo'">
  <new-user-security-info></new-user-security-info>
</div>



new-user.component.ts

import { UserReqViewStateService } from './../../../shared/services/UserManagement/UserReqViewState.service';
// import { PageHeaderModule } from './../../../shared/page-header/page-header.module';
import { UserManagementModule } from './../user-management.module';
import { Component, OnInit, DoCheck } from '@angular/core';
import { routerTransition, slideToRight, slideToLeft } from '../../../router.animations';
import { Router, NavigationEnd } from '@angular/router';

import { NewUserReqComponent } from './new-user-req/new-user-req.component';  //bringing accessability/form validation state from child
import { UserReqValidStateService } from '../../../shared/services/UserManagement/UserReqValidState.service';


@Component({
  selector: 'new-user',
  templateUrl: './new-user.component.html',
  styleUrls: ['./new-user.component.css'],
  host: {
    'class': 'blade-container'
  },
  animations: [slideToRight()]
})
export class NewUserComponent implements OnInit, DoCheck {

  stateUserReq: string = 'userInfo';

  stateUserReqValid: string;

  constructor(private router: Router, private viewstate: UserReqViewStateService, private validstate: UserReqValidStateService) { }

  ngDoCheck() {
    console.log(this.stateUserReqValid)
  }

  ngOnInit() {
    this.viewstate.currentState.subscribe(stateUserReq => this.stateUserReq = stateUserReq)
    this.validstate.currentState.subscribe(stateUserReqValid => this.stateUserReqValid = stateUserReqValid)
  }

  changeViewState(state) {
    this.viewstate.changeState(state);
  }


  private scrollToSectionHook() {
    this.router.events.subscribe(event => {
      if (event instanceof NavigationEnd) {
        const tree = this.router.parseUrl(this.router.url);
        if (tree.fragment) {
          const element = document.querySelector('#' + tree.fragment);
          if (element) {
            setTimeout(() => {
              element.scrollIntoView({ behavior: 'smooth', block: 'end', inline: 'nearest' });
            }, 500);
          }
        }
      }
    });
  }


}

user-management.module.ts

import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ReactiveFormsModule } from '@angular/forms';

import { HttpModule, JsonpModule } from '@angular/http';
import { BrowserModule } from '@angular/platform-browser';
// import 'rxjs/add/operator/map';
import { NgModule, Type, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { CommonModule } from '@angular/common';

import { GridAllModule } from '@syncfusion/ej2-ng-grids';
import { HttpClientModule } from '@angular/common/http';


import {
  GridModule, ToolbarService, EditService, SortService, GroupService, FilterService, PageService,
  ContextMenuItem, PdfExportService, ExcelExportService, ContextMenuService, ResizeService,
  DataSourceChangedEventArgs, DataStateChangeEventArgs
} from '@syncfusion/ej2-ng-grids';


import { UserManagementComponent } from './user-management.component';
import { PageHeaderModule } from './../../shared';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';


// import { NewUserComponent } from './new-user/new-user.component';
// import { PendingUserComponent } from './pending-user/pending-user.component';
// import { ProcessUserComponent } from './process-user/process-user.component';
// import { NewUserReqComponent } from './new-user/new-user-req/new-user-req.component';

import { RouterModule } from '@angular/router';
import { NewUserOrgInfoComponent } from './new-user/new-user-org-info/new-user-org-info.component';
import { NewUserSupervisorInfoComponent } from './new-user/new-user-supervisor-info/new-user-supervisor-info.component';
import { NewUserSecurityInfoComponent } from './new-user/new-user-security-info/new-user-security-info.component'; //??????????
import { NewUserComponent } from './new-user/new-user.component';
import { PendingUserComponent } from './pending-user/pending-user.component';
import { ProcessUserComponent } from './process-user/process-user.component';
import { NewUserReqComponent } from './new-user/new-user-req/new-user-req.component';
import { UserManagementBladeComponent } from './user-management-blade/user-management-blade.component';
import { UserReqValidStateService } from '../../shared/services/UserManagement/UserReqValidState.service';



@NgModule({
  imports: [
    CommonModule,
    PageHeaderModule,
    GridModule,
    RouterModule,
    NgbModule,
    ReactiveFormsModule,
    BrowserAnimationsModule,
    BrowserModule,
    CommonModule
  ],
  declarations: [UserManagementComponent, NewUserComponent, ProcessUserComponent, PendingUserComponent, NewUserReqComponent, NewUserOrgInfoComponent, NewUserSupervisorInfoComponent, NewUserSecurityInfoComponent, UserManagementBladeComponent],
  providers: [EditService, ToolbarService, SortService, GroupService, FilterService, PageService,
    ContextMenuService, PageService, ResizeService, PdfExportService, ExcelExportService, UserReqValidStateService]
})
export class UserManagementModule {
}



app.module.ts

import { PageHeaderModule } from './shared/components/page-header/page-header.module';

import { environment } from './../environments/environment';

// Support imports
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientModule, HttpClient, HTTP_INTERCEPTORS } from '@angular/common/http';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';

// import services
import { WebApiService } from './shared/services/webapi/web-api.service';
import { UserService } from './shared/services/UserManagement/User.service';
import { LogService } from "./shared/services/logging/log.service";
import { LogPublishersService } from "./shared/services/logging/publishers/LogPublishers.service";

// Security
import { GWIAuthService } from "./shared/services/authService/gwiAuth.service";

// Import Components
import { AppComponent } from './app.component';
import { NotFoundComponent } from './not-found/not-found.component';
import { LandingComponent } from './landing/landing.component';

// Import feature modules
import { LayoutModule } from './layout/layout.module';

// Routing Module
import { AppRoutingModule } from './app-routing.module';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { UserManViewStateService } from './shared/services/UserManagement/UserManViewState.service';
import { Guardian } from './shared/services/authService/guardian';
import { UserReqViewStateService } from './shared/services/UserManagement/UserReqViewState.service';
import { UserReqValidStateService } from './shared/services/UserManagement/UserReqValidState.service';




@NgModule({
  declarations: [AppComponent, NotFoundComponent, LandingComponent],
  imports: [
    CommonModule,
    BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
    BrowserAnimationsModule,
    HttpClientModule,
    NgbModule.forRoot(),
    LayoutModule,
    ReactiveFormsModule,
    FormsModule,
    AppRoutingModule,
    PageHeaderModule
  ],
  providers: [
    UserService,
    LogService,
    LogPublishersService,
    WebApiService,
    GWIAuthService,
    UserManViewStateService,
    UserReqViewStateService,
    UserReqValidStateService,
    Guardian
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Answer

Chunbin Li picture Chunbin Li · Jun 3, 2018

you can bind the event to wrapper container(e.x. HTML tag)

<ng-template #ele  >
 <div (click)="changeViewState('userInfo')" class="userManHover" [ngClass]="{'userManSelect': stateUserReq =='userInfo'}">
  ...
  </div>
</ng-template>