Reputation: 9
My problem is the following:
I have stations I want to display inside a modal window, whereas the already selected Stations should be coloured blue and the not selected ones should be gray. All stations are in an array called "allStations" and the already selected stations are in "currentStations".
However, I have multiple problems with this:
First off: I either generate this in HTML with a *for loop, then I have the problem, that I am not able to assign the classes that should colour each one.
<jw-modal id="ov_stations">
<div id="allstationsdiv">
<p *ngFor="let st of allStations" id="{{ st.id }}" class="notselected"(click)="onstationclick({{st.id}})">
{{ st.name }}
</p>
</div>
<span (click)="closemodal()"><img src="../../../../assets/icons/x.png" alt=""></span>
</jw-modal>
I tried to solve this by generating the HTML inside the openmodal() function, which opens the modal in the first place instead of directly in the HTML:
openmodal(){
this.modalService.open("ov_stations");
let output = document.getElementById("allstationsdiv");
let dealtwith = [];
if (output.childElementCount == 0){
for (var i = 0; i < this.allStations.length; i++){
if (this.currentStations.length == 0)
output.innerHTML += "<p id='" + this.allStations[i].id + "' class='notselected' (click)='onstationclick(" + this.allStations[i].id + ")'>" + this.allStations[i].name + "</p>";
else {
// noch weiter testen
for (var j = 0; j < this.currentStations.length; j++){
if (this.currentStations[j].id == this.allStations[i].id){
output.innerHTML += "<p id='" + this.allStations[i].id + "' class='selected' (click)='onstationclick(" + this.allStations[i].id + ")'>" + this.allStations[i].name + "</p>";
dealtwith.push(this.allStations[i].id);
// console.log("selected: " + this.allStations[i].id + " and dealt with: " + dealtwith[i]);
} // && this.allStations[i].id != dealtwith[i]
else if (this.currentStations[j].id != this.allStations[i].id){
output.innerHTML += "<p id='" + this.allStations[i].id + "' class='notselected' (click)='onstationclick(" + this.allStations[i].id + ")'>" + this.allStations[i].name + "</p>";
dealtwith.push(this.allStations[i].id);
// console.log("notselected: " + this.allStations[i].id + " and dealt with: " + dealtwith[i]);
}
console.log(dealtwith);
console.log(this.allStations[i].id);
}
}
}
}
}
(I am aware that the loop doesn't work yet, but that is not my immediate concern)
However, now, when I try to click on a Station to access the function which would change it's class, it does not work anymore, the function is not called upon. I am guessing that this is because I now generate the code inside JS instead of from HTML.
How can I solve this problem? Is there a way to give the p's the correct class with the conditions above? Or is there a way to solve the problem of not being able to get a click function to work from JS?
I would prefer the latter, but if the first one is easier I am willing to try that too. Thank you very much for your time.
Upvotes: 0
Views: 45
Reputation: 56
Using the ngClass directive (https://angular.io/api/common/NgClass) will get you the outcome you are looking for. For example: in your component.html
<div id="allstationsdiv">
<p *ngFor="let st of allStations"
[ngClass]="{
'selected':isStationSelected(st),
'notselected':!isStationSelected(st)
}"
(click)="onstationclick(st.id)">
{{ st.name }}
</p>
</div>
in your component.ts file
export class MyComponent {
allStations = [
{ id: 1, name: "station 1" },
{ id: 2, name: "station 2" },
{ id: 3, name: "station 3" },
{ id: 4, name: "station 4" },
{ id: 5, name: "station 5" }
];
selStations = [{ id: 3, name: "station 3" }, { id: 4, name: "station 4" }];
onstationclick(station): void {
//do something here
}
// will check to see if the currentStations array contains the station id you
// are passing from the all stations array
isStationSelected(station): boolean {
return this.currentStations.some(st=> st.id === station.id);
}
}
in your component.css
.selected {
color: blue
}
.notselected {
color: grey
}
Generally you should avoid generating html code via js in angular, since you have angular itself to do that.
Upvotes: 1