Reputation: 9229
I have an angular2 component which I have included below. I generate a list of chapters
which I then display with an *ngFor=
tag, but I want to be able to individually target these in my ng2 component (so I can highlight the selected chapter). I would of thought the below code would generate something like this:
<p class="chapter 1" #1>1. My First Chapter</p>
However, I don't get the #1, hence my selector doesn't work and I can't by default set the first chapter in the list to be selected.
import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
@Component({
selector: 'tutorial',
template: `
<div class="content row">
<div class="chapters col s3">
<h3>Chapters:</h3>
<p *ngFor="let chapter of chapters" class="chapter" #{{chapter.number}}>{{chapter.number}}. {{chapter.title}}</p>
</div>
</div>
`
})
export class bookComponent implements AfterViewInit {
public chapters = _chapters;
@ViewChild('2') el:ElementRef;
ngAfterViewInit() {
this.el.nativeElement.className += " clicked";
}
}
What should I do to be able to individually select my generated <p>
tags?
Upvotes: 1
Views: 150
Reputation: 657666
For you use case this might be a more angulary way
<p *ngFor="let chapter of chapters; let i=index" (click)="clickedItem = i" [class.clicked]="i == clickedItem" class="chapter" #{{chapter.number}}>{{chapter.number}}. {{chapter.title}}</p>
export class bookComponent implements AfterViewInit {
public chapters = _chapters;
clickedItem: number;
}
Updating the model and binding the view to make Angular reflect the model to the view is the preferred way instead of imperatively modifying the DOM.
Upvotes: 1
Reputation: 55443
You can use directive with HostListener to select an element as shown below.
Working Demo : http://plnkr.co/edit/mtmCKg7kPgZoerqT0UIO?p=preview
import {Directive, Attribute,ElementRef,Renderer,Input,HostListener} from '@angular/core';
@Directive({
selector: '[myAttr]'
})
export class myDir {
constructor(private el:ElementRef,private rd: Renderer){
console.log('fired');
console.log(el.nativeElement);
}
@HostListener('click', ['$event.target'])
onClick(btn) {
if(this.el.nativeElement.className=="selected"){
this.el.nativeElement.className ="";
}else{
this.el.nativeElement.className ="selected";
}
}
}
//our root app component
import {Component} from '@angular/core';
@Component({
selector: 'my-app',
directives:[myDir],
template:
`
<style>
.selected{
color:red;
background:yellow;
}
</style>
<div class="content row">
<div class="chapters col s3">
<h3>Chapters:</h3>
<p myAttr *ngFor="let chapter of chapters" class="chapter" #{{chapter.number}}>{{chapter.number}}. {{chapter.title}}</p>
</div>
</div>
`
})
export class App {
chapters=[{number:1,title:"chapter1"},{number:2,title:"chapter2"},{number:3,title:"chapter3"}]
}
Upvotes: 0
Reputation: 364707
I would let the NgFor loop control adding or removing the clicked
class:
<p *ngFor="let chapter of chapters" class="chapter"
[class.clicked]="chapter.number === selectedChapterNumber">
{{chapter.number}}. {{chapter.title}}
</p>
Then just set selectedChapterNumber
appropriately in your component logic.
export class bookComponent {
public chapters = _chapters;
private selectedChapterNumber = 1;
}
Upvotes: 0