in my component, I have a for-loop with an option-element with a directive. Now i check in the directive if data is available, if no i will remove the ngOption Element from DOM. But this is not working... I see still empty elements in the optionlist.

this.renderer.setStyle(this.el.nativeElement, 'display', 'none');
component.ts
<ng-select id="event1" style="width: 400px; padding-top: 12px"
(change)="search()" [{(ngModel)]="selectedEvent" [disabled]="blockedActionWhileLoading">
<div *ngFor="let event of events">
<ng-option appEventFilter [event]="event">
</ng-option>
</div>
</ng-select>
directive
import { Directive, ElementRef, Input, OnInit, Renderer2 } from '@angular/core';
import { TicketState } from 'src/app/tickets/ticket.model';
import { TicketService } from 'src/app/tickets/ticket.service';
import { Event } from 'src/app/verwaltung/events/event.model';
import { DatePipe } from '@angular/common';
@Directive({
selector: '[appEventFilter]',
})
export class EventFilterDirective implements OnInit {
@Input() event: Event;
constructor(
private ticketService: TicketService,
private el: ElementRef,
private renderer: Renderer2,
private datePipe: DatePipe
) {}
ngOnInit(): void {
let t = this.ticketService.tickets.filter(
(ticket) =>
ticket.event._id === this.event._id && ticket.state === TicketState.NEW
);
if (t.length > 0) {
let datePipeTimeString = this.datePipe.transform(
this.event.date,
'HH:mm'
);
let datePipeDateString = this.datePipe.transform(this.event.date);
this.renderer.setProperty(
this.el.nativeElement,
'innerHTML',
`${this.event.artist.name} - ${this.event.location.city} -
${this.event.location.description} -
${datePipeDateString} -
${datePipeTimeString}
`
);
} else {
console.log('empty');
this.renderer.setStyle(this.el.nativeElement, 'display', 'none');
}
}
}
CodePudding user response:
Personally, I would only render those entries which contain valid data by either filtering them before you write the values in events or with an pipe.
The pipe solution could be the most interesting solutions here because it doesn't modify the original array
filter.pipe.ts
@Pipe({ name: 'filterEvents' })
export class FilterEventsPipe implements PipeTransform {
constructor(private ticketService: TicketService){}
// I only assume that the type is Ticket
transform(tickets: Ticket[]): Ticket[] {
const filteredTickets = tickets.filter(ticket => {
return this.ticketService.tickets.some(
t => t.event.__id === ticket.event._id && t.state === TicketState.NEW
);
});
return filteredTickets;
}
}
And then use the pipe as following:
<div *ngFor="let event of events | filterEvents ">
<ng-option appEventFilter [event]="event"></ng-option>
</div>
With this way you're not only solving your problem with the empty entries, you're also reducing the number of divs on your page because you're only rendering the entries which contain relevant data.
CodePudding user response:
@Batajus
thanks... this is a good solution!... I has to change the Value from Tickets to Events (EventFilter)
import { Pipe, PipeTransform } from '@angular/core';
import { Ticket, TicketState } from 'src/app/tickets/ticket.model';
import { TicketService } from 'src/app/tickets/ticket.service';
import { Event } from 'src/app/verwaltung/events/event.model';
@Pipe({ name: 'filterEvents' })
export class FilterEvents2Pipe implements PipeTransform {
constructor(private ticketService: TicketService) {}
// I only assume that the type is Ticket
transform(events: Event[], tickets: Ticket[]): Event[] {
if (!events) return;
const filteredEvents = events.filter((e) => {
return tickets.some((ticket) => {
return ticket.event._id == e._id && ticket.state == 'NEW';
});
});
return filteredEvents;
}
}
Another question... what is faster... ngIf or a directive? I have a huge list of Data an a lot ngIf's in html. It is better to make a directive for all that?
*ngIf="
ticket.state === TicketState.BILLED ||
ticket.state === TicketState.BILLEDEX ||
ticket.state === TicketState.WRITTENOFF"
