5

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 { }
imnickvaughn
  • 2,774
  • 9
  • 25
  • 42

1 Answers1

5

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>
 
jawath
  • 439
  • 7
  • 22
Chunbin Li
  • 2,196
  • 1
  • 17
  • 31
  • This was not working in my application. I kept getting "Cannot read property 'add' of undefined". Then I made a plunker which doesnt quite work https://stackblitz.com/edit/angular-y1djvk?file=src%2Fapp%2Fapp.component.html – imnickvaughn Jun 04 '18 at 13:59
  • 1
    sorry, it's my mistake, the wrapper container need inside in ng-template, I updated to https://stackblitz.com/edit/angular-g1u9i7 – Chunbin Li Jun 04 '18 at 14:30
  • For anyone wondering.... the error I was getting in my application, "Cannot read property 'add' of undefined", was actually for the [ngClass] on the ng-template. I just moved that to the h4 as well. – imnickvaughn Jun 04 '18 at 14:53
  • yap, you can't put element attributes on an ng-template that it doesn't map to an actual DOM element. – Chunbin Li Jun 04 '18 at 15:29
  • 1
    if you interesting about deep knowledge, you can check [What is the difference between a view, a host view and an embedded view](https://stackoverflow.com/a/45027581/7291379) – Chunbin Li Jun 04 '18 at 15:47
  • I am! Thank you – imnickvaughn Jun 04 '18 at 20:42
  • 1
    if you try to put event for ng-container it does not work. click me – jawath Nov 10 '19 at 14:06
  • @ChunbinLi this helpled me...thanks! Could you please explain why is this working? I only added some #element reference to my ng-template and it's not undefined anymore – Smithy Apr 24 '20 at 13:43
  • @Smithy Would you give me an example that you use? If your question is why not have an event on ng-template. The answer is : **ng-template doesn't map to an actual DOM element.** – Chunbin Li Apr 29 '20 at 09:18
  • @ChunbinLi I use pretty much exactly thing as you do, so , when there was no #someElement it was not working, but with it does. "Bind the event to wrapper container" was the sentence that I found a bit confusing – Smithy Apr 29 '20 at 14:15
  • ng-template is not an actual DOM element, it doesn't have any DOM Event(ex. click event), so I add a DOM element (div) then move click event to div from ng-template. – Chunbin Li Apr 30 '20 at 03:00