I have two tabs on a page and when I delete something from the second tab the page reloads and goes back to the first tab. I need help on how to keep it on the second tab after deletion.
This is the html for the tab group:
<div class="card-header" *ngIf="!loading">
<mat-tab-group (selectedTabChange)="changeActiveTab($event)">
<mat-tab *ngFor="let tab of topTabs" [label]="tab">
</mat-tab>
</mat-tab-group>
</div>
and the delete is an action on a menu that calls the delete function on a click event
<mat-menu #rowActions>
<button mat-menu-item (click)="navigate(['/app/violations/detail/'
+ violation.id])">View
</button>
<button *ngIf="hasWriteAccess" mat-menu-item
(click)="deleteViolation(violation)">Delete
</button>
</mat-menu>
Typescript
export class UnitViolationListComponent implements OnInit,
AfterViewInit
{
@Input() unitId: number = null;
@Input() unit: Unit;
searchValue: string = '';
// Tabs
port class UnitViolationListComponent implements OnInit,
AfterViewInit
{
@Input() unitId: number = null;
@Input() unit: Unit;
searchValue: string = '';
// Tabs
activeTab: string = 'All Outstanding';
topTabs: string [] = [
'All Outstanding',
'Completed',
];
downloadingPdf: boolean = false;
tags: any[] = [];
unitTags: any[] = [];
unitOrgTags: Tag[];
completeViolations: ViolationStatement[] = [];
notCompleteViolations: ViolationStatement[] = [];
violations: ViolationStatement[] = [];
tableDataSource: MatTableDataSource<ViolationStatement> = new
MatTableDataSource<ViolationStatement>();
displayedColumns: string[] = [
'unit',
'title',
'createdAt',
'resolutionTime',
'completedTime',
'actions',
];
pageSizeOptions: number[] = [
25,
50,
100,
200,
];
orgViolationStatuses: ViolationStatus[] = [];
@ViewChild(MatTable) table: MatTable<any>;
@ViewChild(MatPaginator) matpaginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
// Component State
uploading: boolean = false;
loading: boolean = true;
hasWriteAccess: boolean = false;
_jwt: JwtLegFiClaims;
constructor(
private _dialog: MatDialog,
private _fb: FormBuilder,
private _growler: GrowlerService,
private _router: Router,
private _scrollService: ScrollService,
private _violationsService: ViolationsService,
private _csvExportService: CsvExportService,
) {
}
async ngOnInit() {
this._scrollService.scrollToTop();
this._jwt = LegFiJwtService.read();
this.hasWriteAccess =
LegFiJwtService.doesUserHaveModulePermission(
'violation',
true,
);
if (this.unitId) {
this.displayedColumns = this.displayedColumns.filter(c =>
c !== 'unit');
}
if (this._jwt !== null) {
if (this._jwt.superUser || this._jwt.admin) {
this.hasWriteAccess = true;
}
}
await this.getOrgViolationStatuses();
this.getUnitViolations();
}
ngAfterViewInit() {
this.tableDataSource.sort = this.sort;
this.tableDataSource.paginator = this.matpaginator;
const originalFilterFunction =
this.tableDataSource.filterPredicate;
this.tableDataSource.filterPredicate = (data:
ViolationStatement) => {
// and lastly filter on the text string if provided
if (originalFilterFunction(data.unit as any,
this.searchValue)) {
return true;
}
return originalFilterFunction(data, this.searchValue);
};
}
/** Get the available statuses for violations for this org */
async getOrgViolationStatuses() {
await this._violationsService
.getViolationStatusesPromise()
.then(
async (statuses: ViolationStatus[]) => {
this.orgViolationStatuses = statuses;
if (this.orgViolationStatuses.length) {
this.displayedColumns.unshift('status');
// redo the top tabs w custom status
this.topTabs = [
'All Outstanding',
...this.orgViolationStatuses.map(s
=> s.title),
'Completed',
];
}
},
(err: any) => {
console.error('cant get template: ', err);
},
);
}
parseTableDataByStatus() {
if (this.activeTab === 'Completed') {
this.tableDataSource.data = this.completeViolations;
} else if (this.activeTab === 'All Outstanding') {
this.tableDataSource.data = this.notCompleteViolations;
} else if (this.orgViolationStatuses.length) {
this.tableDataSource.data =
this.notCompleteViolations.filter(s => {
return s.status === this.activeTab;
});
}
}
getUnitViolations() {
this.loading = true;
this._violationsService
.getUnitViolations(null, this.unitId)
.pipe(untilDestroyed(this))
.subscribe(async (violations: ViolationStatement[]) =>
{
this.completeViolations = violations.filter(v =>
v.completedTime);
this.notCompleteViolations = violations.filter(v
=> !v.completedTime);
this.parseTableDataByStatus();
this.updateFilter();
this.loading = false;
}, () => {
this.loading = false;
this._growler.error('Error', 'There was an error
loading violations for this unit.');
});
}
/**
* Trigger a re-filter when any of the things we filter by change
*/
updateFilter() {
this.tableDataSource.filter = this.searchValue;
if (this.tags.length > 0) {
this.tableDataSource.filter += '//TAGS//';
}
if (this.unitTags.length > 0) {
this.tableDataSource.filter += '//UNITTAGS//';
}
}
changeActiveTab(event: MatTabChangeEvent) {
this.activeTab = event.tab.textLabel;
// hide the 'completed' column in the table if we are not on
the 'completed' tab
if (this.activeTab === 'Completed') {
this.displayedColumns = [
'unit',
'title',
'createdAt',
'resolutionTime',
'completedTime',
'actions',
];
} else {
this.displayedColumns = [
'unit',
'title',
'createdAt',
'resolutionTime',
'actions',
];
}
if (this.unitId) {
this.displayedColumns = this.displayedColumns.filter(c =>
c !== 'unit');
}
if (this.orgViolationStatuses.length) {
this.displayedColumns.unshift('status');
}
this.parseTableDataByStatus();
this.updateFilter();
}
/**
* Navigate to Request Detail Page
* @param {any[]} routerLink
*/
navigate(routerLink: any[]) {
if (this._jwt !== null) {
// noinspection JSIgnoredPromiseFromCall
this._router.navigate(routerLink);
}
}
deleteViolation(violation: ViolationStatement) {
const baseDialog =
this._dialog.open(ConfirmDeleteModalComponent, {
width: MatDialogSizes.XS,
data: 'violation',
});
baseDialog.afterClosed().subscribe((confirmation: boolean) =>
{
if (confirmation) {
this._violationsService
.deleteViolation([violation.id])
.subscribe(() => {
this.getUnitViolations();
});
}
});
}
exportCsv() {
const c = this.tableDataSource.filteredData.map((v:
ViolationStatement) => {
return new ViolationExportListItem(v);
});
const options = {
headers: [
'status',
'unit',
'title',
'message',
'created',
'resolveBy',
'completed',
'address',
'city',
'state',
'zip',
'comments',
],
showLabels: true,
};
this._csvExportService.generateCsv(c, 'violation-export',
options);
}
exportPdf() {
this.downloadingPdf = true;
this._violationsService.getUnitViolationListPdf(this.unitId,
this.activeTab)
.pipe(untilDestroyed(this))
.subscribe(
response => {
this._csvExportService.downloadFile(response, (this.unitId
? this.unitId + '-'
: '') + this.activeTab + '-
violations.pdf', 'application/pdf');
this.downloadingPdf = false;
},
() => {
this.downloadingPdf = false;
},
);
}
/**
* Handle Toggle of Modals
* @param {boolean} state
* @param {string} modal
*/
toggleModal(state: boolean, modal: string) {
this[modal] = state;
}
}
Is this is something that can be done on the delete function in TS or is there more needed? That is where I need help.
6
When an element is toggled into view using ngIf
, it gets removed completely when the condition is false
, unlike hiding the element using CSS (reference). In your code, getUnitViolations
is called inside of your deleteViolation
function, which then resets the loading
flag, causing your tab group to be removed from the DOM and then re-added.
Some options would be to refactor how you handle loading in the UI or to set selectedIndex on the tab group to control which tab displays.
4