Не удается изменить значок при развертывании / сворачивании для текущего узла - PullRequest
0 голосов
/ 13 марта 2019

Я пытаюсь изменить значок моего узла дерева, когда узел дерева разворачивается или сворачивается. Я успешно могу изменить значок, но проблема в том, что все иконки меняются в дереве. Я только хочу изменить значок узла, на который я нажал. Мой код, как показано ниже:

HTML-файл

<div class="container sidenav-tree">
  <ng-template #recursiveList let-files>
    <div *ngFor="let item of files">
      <div class="row node-item">
        <i
          data-toggle="collapse"
          attr.data-target="#{{item.reference}}"
          class="fa"
          [ngClass]="{'fa-angle-down': isExpanded, 'fa-angle-right': !isExpanded}"
          *ngIf="!(item.children.length===0)"
          (click)="isExpanded=!isExpanded"></i>
        {{item.name}}
      </div>
      <div id="{{item.reference}}" class="container collapse" *ngIf="!(item.children.length===0)">
        <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: item.children }"></ng-container>
      </div>
    </div>
  </ng-template>
  <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: files }"></ng-container>
</div>

и файл компонента:

import {Component, OnInit} from '@angular/core';
import {BlogService} from '../../../../services/blog.service';

@Component({
  selector: 'app-sidenav',
  templateUrl: './sidenav.component.html',
  styleUrls: ['./sidenav.component.css'],
})
export class SidenavComponent implements OnInit {
  files: [];
  selectedFile: string;
  selectedPath: string;
  isExpanded = false;


  constructor(private blogService: BlogService) {
  }

  ngOnInit() {
    this.blogService
      .getTreeNodes()
      .subscribe((files: []) => {
        console.log(files);
        this.files = files;
      });
  }

  nodeSelectEvent(event) {
    this.blogService.selectedNode.next(event.target.innerText);
  }
}

Я хочу максимально сохранить свою логику в файле ts, а не в файле компонента. Пожалуйста, предложите изменения, необходимые в моем коде.

Ответы [ 2 ]

0 голосов
/ 13 марта 2019

Поскольку это рекурсивное дерево произвольной глубины, самое простое объявите объект для моделирования списка файлов, который вы, похоже, извлекаете, и укажите для этого объекта атрибут, который описывает, развернут ли он.

Что-то вроде класса, добавленного к вашему компоненту

public export File{
  Name:string;
  isExanded:boolean;
}

Тогда я бы изменил массив файлов на

files:File[]

Когда вы загружаете данные в подписку, вы можете либо обновить свой сервис для использования аналогичного объекта DTO и вернуть эту коллекцию, либо вы можете перебрать полученный список строк и создать экземпляры объекта File. В настоящее время вы должны инициализировать опцию isExanded в false (если вы не хотите сохранять состояние сервера состояний).

Я бы тогда реализовал обработчик событий в дереве, который обновил состояние текущего файла

toggleFileState(item:File){
  item.isExpanded = !item.isExpanded;
}

Обновите событие щелчка, чтобы вызвать этот обработчик события и передать текущее значение элемента. Также обновите ваш [ngClass], чтобы он ссылался на свойство isExpanded в текущем экземпляре объекта элемента

[ngClass]="{'fa-angle-down':item.isExpanded, 'fa-angle-right':!item.isExpanded'}"
0 голосов
/ 13 марта 2019

Ваш логический isExpanded используется для каждого элемента, поэтому, если элемент меняет значение на true, изменяется состояние всех ваших элементов. Вы должны создать карту для хранения каждого состояния элемента и использовать ее, чтобы определить, является ли узел расширенным или нет.

Я думаю, вы можете использовать item.reference для ключа на карте, чтобы идентифицировать каждый элемент.

Примерно так:

Компонент

import {Component, OnInit} from '@angular/core';
import {BlogService} from '../../../../services/blog.service';

@Component({
  selector: 'app-sidenav',
  templateUrl: './sidenav.component.html',
  styleUrls: ['./sidenav.component.css'],
})
export class SidenavComponent implements OnInit {
  files: [];
  selectedFile: string;
  selectedPath: string;
  isExpanded = false;
  public itemsState = new Map<string, boolean>();


  constructor(private blogService: BlogService) {
  }

  ngOnInit() {
    this.blogService
      .getTreeNodes()
      .subscribe((files: []) => {
        console.log(files);
        this.files = files;
        this.files.forEach(item => {
            // init all items to not expanded
            this.itemsState.set(item.reference, false);
        }
      });
  }

  nodeSelectEvent(event) {
    this.blogService.selectedNode.next(event.target.innerText);
  }
}

HTML:

<div class="container sidenav-tree">
  <ng-template #recursiveList let-files>
    <div *ngFor="let item of files">
      <div class="row node-item">
        <i
          data-toggle="collapse"
          attr.data-target="#{{item.reference}}"
          class="fa"
          [ngClass]="{'fa-angle-down': itemsState.get(item.reference), 'fa-angle-right': !itemsState.get(item.reference)}"
          *ngIf="!(item.children.length===0)"
          (click)="isExpanded=!isExpanded"></i>
        {{item.name}}
      </div>
      <div id="{{item.reference}}" class="container collapse" *ngIf="!(item.children.length===0)">
        <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: item.children }"></ng-container>
      </div>
    </div>
  </ng-template>
  <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: files }"></ng-container>
</div>

Код не проверен, это просто для объяснения принципа

...