当我点击按钮路由到新页面时,该页面上的ngx数据表的数据不会刷新;它只会在我重新加载/刷新页面后刷新。知道我在哪里可能会出错吗?
必要的文件:
溶液list.component.html:
<div class="row">
<div class="col-sm-9 pageTitle">Solutions</div>
<div [hidden]="!busy" class="col-sm-3"><span class="glyphicon glyphicon-refresh glyphicon-spin" style="float:right;"></span></div>
</div>
<div>
<button class="btn btn-default" (click)="createNewButtonClicked()" id="createButton">Create New</button>
<button class="btn btn-default" type="button"(click)="retrieveArchivedButtonClicked()" id="retrieveArchivedButton">Retrieve Archived</button>
<label *ngIf="isAdmin" style="padding-right:2px;">Show All:</label><input *ngIf="isAdmin" type="checkbox" [checked]="showAll" (change)="toggleShowAll()" />
</div>
<ngx-datatable #table
class='datatable'
[sortType]="'single'"
[columns]="columns"
[columnMode]="'flex'"
[headerHeight]="40"
[footerHeight]="50"
[rowHeight]="'auto'"
[limit]="10"
[rows]='rows'>
<template #sortableColumnTemplate let-sort="sortFn" let-column="column" ngx-datatable-header-template>
<span (click)="sort()" class="sort-fullwidth">{{column?.name}}</span>
<input class="filter-box" placeholder='' (keyup)='updateFilter($event)' />
</template>
<template #actionRowTemplate let-row="row" let-value="value" ngx-datatable-cell-template>
<div style="display:block; text-align:center;">
<a title="copy" (click)="copySolution(row)"><i class="button-icon button-icon-copy"></i></a>
<!--<a (click)="copySolution(row)">Copy</a>-->
<!-- | -->
<!--<a (click)="showDeleteConfirmation(row)">Delete</a>-->
<a title="history" (click)="showHistory(row)"><i class="button-icon button-icon-history"></i></a>
<a title="delete" (click)="showDeleteConfirmation(row)" id="delete-{{row.$$index}}"><i class="button-icon button-icon-delete"></i></a>
<!--|
<a (click)="showHistory(row)">History</a>-->
</div>
</template>
<template #customColumnTemplate let-row="row" let-value="value" ngx-datatable-cell-template>
<div style="display:block; text-align:left;">
<a (click)="navigateToEdit(row)">{{row.name}}</a>
</div>
</template>
</ngx-datatable>
<!--<modal #historyModal>
<div class="app-modal-header">
<strong>History for {{solutionHistoryName}}</strong>
</div>
<div class="app-modal-body">
<solution-history [solutionHistories]="solutionHistories"></solution-history>
</div>
<div class="app-modal-footer">
<button type="button" class="btn btn-default" (click)="historyModal.hide()">Close</button>
</div>
</modal>-->
<modal #deleteModal>
<div class="app-modal-header" style="border:none;">
</div>
<div class="app-modal-body">
Confirm deletion of <span style="font-weight:bold;">{{solutionToDelete?.name}}</span> and it's associated project.
</div>
<div class="app-modal-footer">
<button type="button" class="btn btn-default" (click)="deleteModal.hide()" id="cancelDeleteButton">Cancel</button>
<button type="button" class="btn btn-danger" (click)="deleteSolution()" id="confirmDeleteButton">Confirm</button>
</div>
</modal>
溶液list.component.ts:
import { Component, OnInit, ViewChild } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { SolutionMetadata, SolutionHistory } from '../../models/solution.models';
import { SolutionHistoryComponent } from './subcomponents/solution-history.component';
import { GridComponent } from '../../components/shared/util/grid.component';
import { ModalComponent } from '../../components/shared/util/modal.component';
import { UserRoleService } from "../../services/userRole.service";
import { SolutionManagementService } from '../../services/solutionManagement.service';
import { SolutionService } from '../../services/solution.service';
import { ToasterNotificationService } from '../../services/toasternotification.service';
import { AuthHttp } from 'ng2-adal/core';
@Component({
selector: 'solution-list',
templateUrl: './solution-list.component.html',
styleUrls: ['../shared/util/grid.component.css',
'../shared/util/form-sharedstyle.css',
'./solution-list.component.css']
})
export class SolutionListComponent extends GridComponent {
solutions: SolutionMetadata[];
isAdmin: boolean = false;
showAll: boolean = false;
busy: boolean = false;
userName: string;
solutionHistories: SolutionHistory[];
solutionToDelete: SolutionMetadata;
solutionHistoryName: string;
@ViewChild('deleteModal') deleteModal: ModalComponent;
constructor(private _solutionService: SolutionService,
private _router: Router,
private _activatedRoute: ActivatedRoute,
private _solutionManagementService: SolutionManagementService,
private _userRoleService: UserRoleService,
private toasterService: ToasterNotificationService,
authHttp: AuthHttp) {
super(false, authHttp);
}
ngOnInit() {
super.ngOnInit();
this.initDataTable();
this._solutionManagementService.ClearAll();
this._solutionService.Solutions.subscribe(data => {
this.busy = false;
this.solutions = data;
this.updateRows(this.showAll ? data : data.filter(it => it.owner == this.userName || it.authorizedUsers.indexOf(this.userName) >= 0));
});
this.userName = this._userRoleService.getUserName();
this.isAdmin = this._userRoleService.isInRole(this._userRoleService.roles.AdminRole);
//this.isAdmin = true;
if (this.isAdmin) {
this._solutionService.getAllSolutionSummaries().subscribe(
() => { }, // handled in Solutions subscription callback
(error: any) => {
this.toasterService.Notify("Error", "An error occured while retrieving the solutions.");
this.table.messages.emptyMessage = "No records."
});
}
else {
this._solutionService.getSolutionSummaries().subscribe(
() => { }, // handled in Solutions subscription callback
(error: any) => {
this.toasterService.Notify("Error", "An error occured while retrieving the solutions.");
this.table.messages.emptyMessage = "No records."
});
}
}
copySolution(solution: SolutionMetadata) {
this.busy = true;
this._solutionService.copySolution(solution.id).subscribe(
() => { }, // handled in Solutions subscription callback
(error: any) => {
this.busy = false;
this.toasterService.Notify("error", "An error occured while copying solution " + solution.name);
});
}
navigateToEdit(solutionSummary: SolutionMetadata) {
this._router.navigate(['solutions/edit', solutionSummary.id]);
}
//RTH - Will need to be renamed properly later. Show history in V7 is its own view.
showHistory(solutionSummary: SolutionMetadata) {
this._router.navigate(['solutions/history/' + solutionSummary.id]);
}
showDeleteConfirmation(solutionSummary: SolutionMetadata) {
this.solutionToDelete = solutionSummary;
this.deleteModal.show();
}
deleteSolution() {
if (this.solutionToDelete)
{
this.busy = true;
this.deleteModal.hide();
this._solutionService.deleteSolution(this.solutionToDelete.id).subscribe(
() => { },
(error: any) => {
this.busy = false;
this.toasterService.Notify("error", "An error occured while deleting the solution.");
});
}
}
toggleShowAll()
{
this.showAll = !this.showAll;
if (this.showAll && this.solutions) {
this.updateRows(this.solutions);
}
else if (this.solutions)
{
this.updateRows(this.solutions.filter(it => it.owner == this.userName || it.authorizedUsers.indexOf(this.userName) >= 0));
}
}
initDataTable() {
this.columns = [
{
name: 'Solution Name',
prop: 'name',
sortable: true,
sortString: '',
flexGrow: 2,
cellTemplate: this.customColumnTemplate,
headerTemplate: this.sortableColumnTemplate
},
{
name: 'Description',
prop: 'description',
sortable: true,
sortString: '',
flexGrow: 3,
headerTemplate: this.sortableColumnTemplate
},
{
name: 'Solution Owner',
prop: 'owner',
sortable: true,
sortString: '',
flexGrow: 2,
headerTemplate: this.sortableColumnTemplate
},
{
name: '# RGs',
prop: 'resourceGroupCount',
sortable: true,
sortString: '',
flexGrow: .7,
headerTemplate: this.sortableColumnTemplate
},
{
name: 'Version',
prop: 'version',
sortable: true,
sortString: '',
flexGrow: 1,
headerTemplate: this.sortableColumnTemplate
},
{
name: 'Action',
cellTemplate: this.actionRowTemplate,
sortable: false,
flexGrow: 2
}
];
}
createNewButtonClicked() {
this._router.navigate(['/solutions/create']);
}
retrieveArchivedButtonClicked() {
this._router.navigate(['/solutions/retrievearchived']);
}
}
solution.service.ts:
import { Injectable } from '@angular/core';
import { Http, RequestOptions, Headers } from '@angular/http';
import { Observable, Subject } from 'rxjs';
import { Solution, SolutionMetadata, SolutionHistory, SolutionComparison, Landscape } from '../models/solution.models';
import { LandscapeDetail } from '../components/designer/models/landscape-detail.models';
import { AuthHttp } from 'ng2-adal/core';
@Injectable()
export class SolutionService
{
private _solutions: SolutionMetadata[];
public Solutions: Subject<SolutionMetadata[]>;
constructor(private _http: AuthHttp) {
this.Solutions = new Subject<SolutionMetadata[]>();
}
getSolutionSummaries(): Observable<SolutionMetadata[]>
{
if (this._solutions)
{
this.Solutions.next(this._solutions);
return Observable.of(this._solutions);
}
else {
return this._http.get('api/solutions')
.map(response => response.json() as SolutionMetadata[])
.do(solutions => {
this._solutions = solutions;
this.Solutions.next(this._solutions);
return solutions;
});
}
}
getAllSolutionSummaries(): Observable<SolutionMetadata[]>
{
if (this._solutions) {
this.Solutions.next(this._solutions);
return Observable.of(this._solutions);
}
else {
return this._http.get('api/solutions/all')
.map(response => response.json() as SolutionMetadata[])
.do(solutions => {
this._solutions = solutions;
this.Solutions.next(this._solutions);
return solutions;
});
}
}
getSolution(id: string): Observable<Solution>
{
return this._http.get('api/solutions/details/' + id)
.map(response => response.json() as Solution);
}
createSolution(solution: Solution): Observable<Solution>
{
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({
headers: headers
});
return this._http.post('api/solutions/create', JSON.stringify(solution), options)
.map(response => response.json() as Solution)
.do(solution => {
let metadata = this.createMetadataFromSolution(solution);
if (!this._solutions) {
this._solutions = [];
}
this._solutions.unshift(metadata);
this.Solutions.next(this._solutions);
return solution;
});
}
editSolution(solution: any): Observable<SolutionMetadata>
{
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({
headers: headers
});
return this._http.post('api/solutions/edit', JSON.stringify(solution), options)
.map(response => response.json() as SolutionMetadata)
.do(metadata => {
let index = this._solutions.findIndex(it => it.id == solution.id);
this._solutions[index] = metadata;
this.Solutions.next(this._solutions);
return metadata;
});
}
copySolution(id: string): Observable<any>
{
return this._http.get('api/solutions/copy/' + id)
.map(response => response.json() as SolutionMetadata)
.do(metadata => {
this._solutions.unshift(metadata);
this.Solutions.next(this._solutions);
});
}
//Checks if solution needs to be converted from CloudShaper and/or returns solution.
getOrConvertSolution(id: string): Observable<Solution> {
return this._http.get('api/solutions/getOrConvert/' + id)
.map(response => response.json() as Solution);
}
getHistories(id: string): Observable<SolutionHistory[]> {
return this._http.get('api/solutions/histories/' + id)
.map(response => response.json() as SolutionHistory[]);
}
getComparison(archiveId: string, solutionId: string): Observable<SolutionComparison> {
let parameters = '?archiveId=' + archiveId + '&solutionId=' + solutionId;
return this._http.get('api/solutions/compare' + parameters)
.map(response => response.json() as SolutionComparison)
}
deleteSolution(id: string): Observable<any> {
return this._http.delete('api/solutions/' + id)
.do(data => {
let index = this._solutions.findIndex(it => it.id == id);
this._solutions.splice(index, 1);
this.Solutions.next(this._solutions);
});
}
deleteSolutionFromProjectsList(id: string): Observable<any> {
return this._http.delete('api/solutions/' + id);
}
deleteLandscape(solutionId: string, landscapeName: string): Observable<any> {
let url = "api/solutions/landscape?solutionId=" + solutionId + "&landscapeName=" + landscapeName;
return this._http.delete(url);
}
saveLandscapeDetail(solutionId: string, landscapeDetails: LandscapeDetail): Observable<Solution> {
let url: string = 'api/solutions/saveLandscapeDetail/' + solutionId;
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({
headers: headers
});
return this._http.post(url, JSON.stringify(landscapeDetails), options)
.map(response => response.json() as Solution);
}
saveLandscape(solutionId: string, landscape: Landscape): Observable<any> {
let url: string = 'api/solutions/landscape?solutionId=' + solutionId;
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({
headers: headers
});
return this._http.post(url, JSON.stringify(landscape), options)
.map(response => response._body as string);
}
copyLandscape(solutionId: string, sourceLandscapeName: string, targetLandscapeName: string): Observable<any> {
let url: string = 'api/solutions/landscape/copy?solutionId=' + solutionId
+ '&sourceLandscapeName=' + sourceLandscapeName
+ '&targetLandscapeName=' + targetLandscapeName;
return this._http.get(url)
.map(response => response.json() as Landscape);
}
isUniqueName(solutionName: string): Observable<boolean>
{
let url: string = 'api/solutions/isUniqueName?name=' + solutionName;
return this._http.get(url)
.map(response => response.json() as boolean)
}
private createMetadataFromSolution(solution: Solution): SolutionMetadata
{
return <SolutionMetadata>{
id: solution.id,
name: solution.name,
description: solution.description,
resourceGroupCount: 0,
owner: solution.createdBy,
version: solution.version,
useTags: solution.taggingEnabled,
createdOn: solution.createdOn,
createdBy: solution.createdBy,
editedBy: solution.editedBy,
editedOn: solution.editedOn,
cloudserviceType: solution.landscapeDetail.cloudServiceProvider
};
}
}
存档溶液-list.component.ts:
import { Component, OnInit, ViewChild } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { SolutionMetadata, SolutionHistory } from '../../models/solution.models';
import { SolutionHistoryComponent } from './subcomponents/solution-history.component';
import { ArcGridComponent } from '../../components/shared/util/arc-grid.component';
import { GridComponent } from '../../components/shared/util/grid.component';
import { ModalComponent } from '../../components/shared/util/modal.component';
import { UserRoleService } from "../../services/userRole.service";
import { SolutionManagementService } from '../../services/solutionManagement.service';
import { ArchivedSolutionService } from '../../services/archivedSolution.service';
//import { SolutionService } from '../../services/solution.service';
import { ToasterNotificationService } from '../../services/toasternotification.service';
import { AuthHttp } from 'ng2-adal/core';
@Component({
selector: 'archived-solution-list',
templateUrl: './archived-solution-list.component.html',
styleUrls: ['../shared/util/arc-grid.component.css',
'../shared/util/form-sharedstyle.css',
'./archived-solution-list.component.css']
})
export class ArchivedSolutionListComponent extends ArcGridComponent {
solutions: SolutionMetadata[];
isAdmin: boolean = false;
showAll: boolean = false;
busy: boolean = false;
userName: string;
solutionHistories: SolutionHistory[];
solutionToDelete: SolutionMetadata;
solutionHistoryName: string;
isRetrieveArchivedClicked: boolean = false;
@ViewChild('archivedSolutionsModal') archivedSolutionsModal: ModalComponent;
constructor(private _archivedSolutionService: ArchivedSolutionService,
private _router: Router,
private _activatedRoute: ActivatedRoute,
private _solutionManagementService: SolutionManagementService,
private _userRoleService: UserRoleService,
private toasterService: ToasterNotificationService,
authHttp: AuthHttp) {
super(false, authHttp);
}
ngOnInit() {
super.ngOnInit();
this.initArcDataTable();
this._solutionManagementService.ClearAll();
this._archivedSolutionService.Solutions.subscribe(data => {
this.busy = false;
this.solutions = data;
this.updateRows2(this.showAll ? data : data.filter(it => it.owner == this.userName || it.authorizedUsers.indexOf(this.userName) >= 0));
});
this.userName = this._userRoleService.getUserName();
//this.isAdmin = true;
this.isAdmin = this._userRoleService.isInRole(this._userRoleService.roles.AdminRole);
if (this.isAdmin) {
this._archivedSolutionService.getAllArchivedSolutionSummaries().subscribe(
() => { }, // handled in Solutions subscription callback
(error: any) => {
this.toasterService.Notify("Error", "An error occured while retrieving the archived solutions.");
this.table2.messages.emptyMessage = "No records."
});
}
else {
this._archivedSolutionService.getArchivedSolutionSummaries().subscribe(
() => { }, // handled in Solutions subscription callback
(error: any) => {
this.toasterService.Notify("Error", "An error occured while retrieving the archived solutions.");
this.table2.messages.emptyMessage = "No records."
});
}
}
restoreSolution() {
console.log("Restore Solution clicked!");
}
toggleShowAll() {
this.showAll = !this.showAll;
if (this.showAll && this.solutions) {
this.updateRows2(this.solutions);
}
else if (this.solutions) {
this.updateRows2(this.solutions.filter(it => it.owner == this.userName || it.authorizedUsers.indexOf(this.userName) >= 0));
}
}
initArcDataTable() {
this.columns2 = [
{
name: 'Solution',
prop: 'name',
sortable: true,
sortString: '',
flexGrow: 2,
cellTemplate: this.customColumnTemplate2,
headerTemplate: this.sortableColumnTemplate2
},
{
name: 'Description',
prop: 'description',
sortable: true,
sortString: '',
flexGrow: 3,
headerTemplate: this.sortableColumnTemplate2
},
{
name: 'Solution Owner',
prop: 'owner',
sortable: true,
sortString: '',
flexGrow: 2,
headerTemplate: this.sortableColumnTemplate2
},
{
name: '# RGs',
prop: 'resourceGroupCount',
sortable: true,
sortString: '',
flexGrow: .7,
headerTemplate: this.sortableColumnTemplate2
},
{
name: 'Version',
prop: 'version',
sortable: true,
sortString: '',
flexGrow: 1,
headerTemplate: this.sortableColumnTemplate2
},
{
name: 'Action',
cellTemplate: this.actionRowTemplate2,
sortable: false,
flexGrow: 2
}
];
}
}