Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can I use ngClass on the ng-template? #89

Open
marlboroman3 opened this issue Feb 12, 2018 · 6 comments
Open

Can I use ngClass on the ng-template? #89

marlboroman3 opened this issue Feb 12, 2018 · 6 comments

Comments

@marlboroman3
Copy link

Id like to add a class to a menu item conditionally.

<ng-template contextMenuItem (execute)="doSomething($event.item)" [ngClass]="{'first': true}">

but get a console error: TypeError: Cannot read property 'add' of undefined

Even better, I'd like to reference the item's properties, like
[ngClass]="{'first': $event.item.isSnapToGrid}"

but I get: ReferenceError: $event is not defined

@isaacplmann
Copy link
Owner

You can't put element attributes on an <ng-template> since it doesn't map to an actual DOM element. The best you can do is this:

<ng-template contextMenuItem (execute)="doSomething($event.item)">
  <div [ngClass]="{'first': true}"></div>
</ng-template>

If all you want to do is write a css rule for the first context menu item, you can do that without a class.

.ngx-contextmenu li:first-child {
  background-color:red;
}

@marlboroman3
Copy link
Author

marlboroman3 commented Feb 18, 2018

Yes, I expect your solution would generally work in pure HTML. Alas, my context menu is defined in the middle of SVG markup, which generally works, but chokes on having a <div> (or <span>, for that matter) inline in the SVG:

<svg:g *ngFor="let thing of things">[contextMenu]="thingMenu" [contextMenuSubject]="thing"></svg:g>
<context-menu #thingMenu>
      <ng-template contextMenuItem (execute)="toggleThing($event.item)">
            <div [ngClass]="{'my-special-class': $event.item.isThingSpecial}">Do something</div>
      </ng-template>
</context-menu>

My use case is to use .my-special-class:after pseudo selector to annotate and style the menu item text conditionally with CSS. (this 'first' example I used was simply an example taken from the angular docs to illustrate a point)

@isaacplmann
Copy link
Owner

The <context-menu> itself actually gets injected just above the </body> closing tag, so it shouldn't be in the middle of your svg. Is angular not letting you compile with the <div> tag inside the <ng-template> in the svg? What is the error you get?

@marlboroman3
Copy link
Author

Yeah, that is precisely the problem. My entire component template is SVG, no HTML at all, until I add the <div>. The error in the console is (I've refactor somewhat, but with the same result):

Uncaught Error: Template parse errors:
':svg:div' is not a known element:
1. If ':svg:div' is an Angular component, then verify that it is part of this module.
2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("menu #pieceMenu>
			<ng-template contextMenuItem (execute)="splitPiece()" [enabled]="canSplit">
				[ERROR ->]<div>Split Piece</div>
			</ng-template>
		</context-menu>
"): ng:///AppModule/PieceComponent.html@7:4
    at syntaxError (webpack-internal:///../../../compiler/esm5/compiler.js:706)
    at TemplateParser.parse (webpack-internal:///../../../compiler/esm5/compiler.js:24888)
    at JitCompiler._parseTemplate (webpack-internal:///../../../compiler/esm5/compiler.js:34841)
    at JitCompiler._compileTemplate (webpack-internal:///../../../compiler/esm5/compiler.js:34816)
    at eval (webpack-internal:///../../../compiler/esm5/compiler.js:34717)
    at Set.forEach (<anonymous>)
    at JitCompiler._compileComponents (webpack-internal:///../../../compiler/esm5/compiler.js:34717)
    at eval (webpack-internal:///../../../compiler/esm5/compiler.js:34587)
    at Object.then (webpack-internal:///../../../compiler/esm5/compiler.js:695)
    at JitCompiler._compileModuleAndComponents (webpack-internal:///../../../compiler/esm5/compiler.js:34586)

@isaacplmann
Copy link
Owner

Here's what I would do:

  1. Declare your <context-menu> somewhere outside of the svg components.
  2. Pass the thingMenu reference down into your component as an Input (or you can provide it using a service)
  3. Your template is now just:
<svg:g *ngFor="let thing of things">[contextMenu]="thingMenu" [contextMenuSubject]="thing"></svg:g>

@demonguru18
Copy link

demonguru18 commented Sep 20, 2019

In you css file =>
.loading { margin: 10% 0 0 50%; }

In the HTML file =>

<ng-template #loading>
  <div class="loading">
    <img  src="/images/spinner.gif" />
  </div>
</ng-template>

OR
In you css file =>
.loading { margin: 10% 0 0 50%; }

In the HTML file =>

<ng-template #loading>
  <div [class.loading]="product.loading">
    <img  src="/images/spinner.gif" />
  </div>
</ng-template>

In the component file .ts

/*Declare property*/
product : Product;

/*Initialize property*/
ngOnInit() { 
this.product = {"name" : "iphone",  "loading" : true};
}


In the Interface file declare custom type property

export interface Product {
  name : string;
  loading : boolean; 
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants