Angular 6材质树视图

时间:2018-09-12 13:00:27

标签: angular angular-material angular6

我正在使用Angular Material v6。我正在尝试从服务器上的JSON文件动态创建树。当前,树可以创建父级,但不能创建子级。控制台正确输出父级和子级。但是,我似乎找不到此问题的根源。

这是我的代码:

testcasefolder-list.component.html:

<mat-tree [dataSource]="nestedDataSource" [treeControl]="nestedTreeControl" class="example-tree">
  <mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle>
    <li class="mat-tree-node">
      <button mat-icon-button disabled></button>
      {{node.category.name}}
    </li>
  </mat-tree-node>

  <mat-nested-tree-node *matTreeNodeDef="let node; when: hasNestedChild">
    <li>
      <div class="mat-tree-node">
        <button mat-icon-button matTreeNodeToggle
                [attr.aria-label]="'toggle ' + node.filename">
          <mat-icon class="mat-icon-rtl-mirror">
            {{nestedTreeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
          </mat-icon>
        </button>
        {{node.category.name}}
      </div>
      <ul [class.example-tree-invisible]="!nestedTreeControl.isExpanded(node)">
        <ng-container matTreeNodeOutlet></ng-container>
      </ul>
    </li>
  </mat-nested-tree-node>
</mat-tree>

testcasefolder-list.component.ts:

import { TestcasefolderService } from './../../services/testcasefolder-service';
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { NestedTreeControl } from '@angular/cdk/tree';
import { MatTreeNestedDataSource } from '@angular/material';
import { of } from 'rxjs';
import { ITestcasefolder } from '../../model/itestcasefolder';
export class CategoryNode {
  children: CategoryNode[ ];
  category: ITestcasefolder;
}
@Component({
  selector: 'app-testcasefolder-list',
  templateUrl: './testcasefolder-list.component.html',
  styleUrls: ['./testcasefolder-list.component.css']
})
export class TestcasefolderListComponent implements OnInit {
// Does not follow main/sub category - just has a simple category!
@Input() categoryID: number;
@Output() categoryIDChange: EventEmitter<number> = new EventEmitter<number>();

nestedTreeControl: NestedTreeControl<CategoryNode>;
nestedDataSource: MatTreeNestedDataSource<CategoryNode>;
type: any;
hasNestedChild = (_: number, nodeData) => !(nodeData.type);

constructor(
  private dataBrokerService: TestcasefolderService
) {
  this.nestedTreeControl = new NestedTreeControl(node => of(node.children));
  this.nestedDataSource = new MatTreeNestedDataSource();
}

ngOnInit() {
  this.dataBrokerService.getTestcasefolders().subscribe(categories => this.nestedDataSource.data = this.buildTree(categories));
}

onChange() {
  this.categoryIDChange.emit(this.categoryID);
}

private buildTree(categories: ITestcasefolder[]): CategoryNode[] {

  const tree: CategoryNode[] = [];
  const map: {[s: number]: CategoryNode} = {};

  // Build an index of the nodes
  categories.forEach(cat => {
    map[cat.id] = {children: [], category: cat};
  });
  console.log(tree);
  // Start adding nodes to tree
  for (const key of Object.keys(map)) {
    const catNode = map[+key];

    if (map[catNode.category.parentid]) {
      // Add it to the parent
      map[catNode.category.parentid].children.push(catNode);
    } else {
      // Add it to root
      tree.push(catNode);
    }
  }
  console.log(tree);
  return tree;
}

}

testcasefolder-service.ts:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { catchError, map, tap } from 'rxjs/operators';
import { of, Observable } from 'rxjs';
import { MessageService } from './message-service.service';
import { ITestcasefolder } from '../model/itestcasefolder';
import { Global } from '../shared/Global';


const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};

@Injectable({
  providedIn: 'root'
})
export class TestcasefolderService {

  private testcasefolderServiceUrl = Global.BASE_USER_ENDPOINT +  'testcasefolders';

  constructor(private http: HttpClient, private messageService: MessageService) { }

  private log(message: string) {
    this.messageService.add(`TestcasefolderService: ${message}`);
  }


  getTestcasefolders(): Observable<ITestcasefolder[]> {
  return this.http.get<ITestcasefolder[]>(this.testcasefolderServiceUrl)
    .pipe(
      tap(requirements => this.log('fetched testcasefolder')),
      catchError(this.handleError('getTestcasefolders', []))
    );
 }

 getTestcasefolder(id: string): Observable<ITestcasefolder> {
  const url = `${this.testcasefolderServiceUrl}/${id}`;
  return this.http.get<ITestcasefolder>(url).pipe(
    tap(_ => this.log(`fetched testcasefolder id=${id}`)),
    catchError(this.handleError<ITestcasefolder>(`get testcasefolder id=${id}`))
  );
 }

addTestcasefolder(testcasefolder: ITestcasefolder): Observable<ITestcasefolder> {
delete testcasefolder['id'];
 return this.http.post<ITestcasefolder>(this.testcasefolderServiceUrl, testcasefolder, httpOptions)
// tslint:disable-next-line:no-shadowed-variable
.pipe(tap((testcasefolder: ITestcasefolder) => this.log(`added testcasefolder w/ id= ${testcasefolder.id}`)),
catchError(this.handleError<ITestcasefolder>('addTestcasefolder'))
);
}

updateTestcasefolder(testcasefolder: ITestcasefolder): Observable<any> {
  const url = `${this.testcasefolderServiceUrl}/${testcasefolder.id}`;
  return this.http.put(url, testcasefolder, httpOptions)
  .pipe(tap(_ => this.log(`updated testcasefolder id=${testcasefolder.id}`)),
  catchError(this.handleError<any>('updateTestcasefolder')));
}
deleteTestcasefolder(testcasefolder: ITestcasefolder |  string ): Observable<ITestcasefolder> {
const id = typeof testcasefolder === 'string' ? testcasefolder : testcasefolder.id;
const url = `${this.testcasefolderServiceUrl}/${id}`;
return this.http.delete<ITestcasefolder>(url, httpOptions)
.pipe(
  tap(_ => this.log(`deleted testcasefolder`)),
  catchError(this.handleError<ITestcasefolder>(`deletedTestcasefolder`))
);
}

 private handleError<T> (operation = 'operation', result?: T) {
   return (error: any): Observable<T> => {

     // TODO: send the error to remote logging infrastructure
     console.error(error); // log to console instead

     // TODO: better job of transforming error for user consumption
     this.log(`${operation} failed: ${error.message}`);

     // Let the app keep running by returning an empty result.
     return of(result as T);
   };
 }
}

itestcasefolder.ts:

export class ITestcasefolder {
    id?: string;
    name?: string;
    description?: string;
    parentid?: string;
    children?: ITestcasefolder[];
}

0 个答案:

没有答案