Luffy1
@Luffy1
Student, Junior .NET programmer, C#, JS, HTML/CSS

Как передать данные из дочернего компонента в родительский?

Parent component:
.ts:
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component,  HostListener,  OnInit } from '@angular/core';
import { MainInteractComponent } from '../main-interact/main-interact.component';
import { HotKeys } from '../Enums/hot-keys';
import { NodeElement, NodeParameter } from '../Models/Node';

@Component({
  selector: 'node-interactive-list',
  templateUrl: './node-interactive-list.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  styleUrls: ['./node-interactive-list.component.css']
})
export class NodeInteractiveListComponent implements OnInit {
  nodes: NodeElement[] = [];
  activeIndex = -1;
  activeElement: NodeElement = null;

  constructor(private parent: MainInteractComponent,
    private http: HttpClient,
    private ref: ChangeDetectorRef
     ) {
  }

  ngOnInit(): void {
  }


  @HostListener('document:keydown', ['$event'])
  handleKeyboardEvent(e: any) {
    if (e.altKey && e.keyCode === HotKeys.PressN) {
      e.preventDefault();
      this.ref.detectChanges();
      this.addEmptyNode();
    }
    if (e.altKey && e.keyCode === HotKeys.PressS) {
      //e.preventDefault();

      //const model: any = {
      //  id: this.activeElement.id,
      //  properties: Object.assign({}, ...this.activeElement.parameters.concat([new NodeParameter("name", this.activeElement.name.toString())], this.activeElement.parameters)
      //    .map((x) => ({ [x.name.toString()]: x.value.toString() })))
      //};
      //if (!this.activeElement.id) {
      //  const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
      //  return this.http.post('https://localhost:44350/Node',
      //    JSON.stringify(model), { headers }).subscribe((x: any) => {
      //      this.activeElement.id = x.id;
      //    });
      //}
      //else {
      //  const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
      //  return this.http.put('https://localhost:44350/Node/' + this.activeElement.id,
      //    JSON.stringify(model), { headers }).subscribe((x: any) => { });
      //}
    }

    if (e.altKey && e.keyCode === HotKeys.PressR) {
      //if (this.activeElement.id != null) {
      //  this.http.delete('https://localhost:44350/Node/' + `${this.activeElement.id}`)
      //    .subscribe(() => {
      //      this.activeElement = new NodeElement();
      //      this.ref.detectChanges();
      //    });
      //}
    }
    if (e.keyCode === HotKeys.ArrowUp) {

      if (this.activeIndex > 0) {
        this.activeIndex--;
        this.activeElement = this.nodes[this.activeIndex];
        this.ref.detectChanges();
      }
    }

    if (e.keyCode === HotKeys.ArrowDown) {
      if (this.activeIndex < this.nodes.length - 1) {
        this.activeIndex++;
        this.activeElement = this.nodes[this.activeIndex];
        this.ref.detectChanges();
      }
    }
  }

  addEmptyNode() {
    if (this.nodes.length == 0 || !this.nodes[this.nodes.length - 1].isClean()) {
      let newNode = new NodeElement();
      this.nodes.push(newNode);
      this.activeIndex = this.nodes.length - 1;
      this.activeElement = this.nodes[this.activeIndex];
      this.ref.detectChanges();
    }

  }
}


.html:
<app-node-item *ngIf="activeElement" [node]="activeElement"></app-node-item>
  <!--Property code doesn't exist, it's mistake. I suppose I will need to to replace it-->


Child component:
.ts:
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { ChangeDetectorRef, Component, HostListener, Input, OnInit } from '@angular/core';
import { HotKeys } from '../Enums/hot-keys';
import { NodeElement, NodeParameter } from '../Models/Node';

@Component({
  selector: 'app-node-item',
  templateUrl: './node-item.component.html',
  styleUrls: ['./node-item.component.css']
})
export class NodeItemComponent implements OnInit {

  @Input() currentNode: NodeElement = new NodeElement();

  public currentSelectedIndex: number = -1;
  public searchResults: any[] = [];
    
  constructor(private http: HttpClient,
    private ref: ChangeDetectorRef  ) { }
  
  ngOnInit(): void {
  }

  @HostListener('document:keydown', ['$event'])
  handleKeyboardEvent(e: any) {
    if ((e.srcElement.classList[0] == 'name-input' || e.srcElement.classList[1] == 'name-input') && !this.currentNode.id) {
      setTimeout(() => {
        const model: any = {
          properties: {
            'name': this.currentNode.name.toString()
          }
        };
        const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
        return this.http.post('https://localhost:44350/Node/specs',
          JSON.stringify(model), { headers }).subscribe((x: any) => {
            this.searchResults = x.map(node => {
              var result: [string, string][] = Object.entries(node.properties)
              var resultNode: NodeElement = new NodeElement();
              resultNode.parameters = result.map(y => new NodeParameter(y[0], y[1])).filter(z => z[0] != 'name');
              resultNode.id = node.id;
              resultNode.name = result.filter(z => z[0] == 'name')[0][1];
              return resultNode;
            });
            this.ref.detectChanges();
          });
      }, 0)
      
    }
    if (e.altKey && e.keyCode === HotKeys.PressF) {
      e.preventDefault();
      if (this.currentSelectedIndex == -1) {
        this.currentNode.parameters.push(new NodeParameter('', ''));
      }
      else {
        this.currentNode.parameters.splice(this.currentSelectedIndex+1, 0, new NodeParameter('', ''));
      }
      setTimeout(() => {
        if (this.currentSelectedIndex != -1) {
          e.srcElement.parentNode.nextSibling.children[1].focus()
        }
      }, 0)
    }
    if (e.altKey && e.keyCode === HotKeys.PressD) {
      e.preventDefault();
      this.currentNode.parameters = this.currentNode.parameters.filter((x, i) => i != this.currentSelectedIndex);
      if (this.currentSelectedIndex != -1 && this.currentSelectedIndex != -1 && !!e.srcElement.parentNode.previousSibling.children[1]) {
        e.srcElement.parentNode.previousSibling.children[1].focus()
      }
    }
  }

  public getHints(option: any) {
    if (!!option)
      return (option.name);
    else
      return ''
  }

  public getName() {
    if (!!this.currentNode?.name) return !!this.currentNode?.name; else new NodeElement();
  }
  public setName(event) {
    if (!!this.currentNode?.name)
      this.currentNode.name = event;
  }

  public getParameters() {
    if (!!this.currentNode?.parameters)
      return this.currentNode?.parameters
    else return [];
  }

  public onParameterFocus(i: number) {
    setTimeout(() => {
      this.currentSelectedIndex = i;
    }, 0)
    
  }
  public onParameterBlur() {
    this.currentSelectedIndex = -1;
  }

  displayFn = state => {
    if (!!state) {
      this.currentNode = state;
      return state?.name;
    }
  }

}


.html:
<p>name:</p>
<input class="name-input" type="text" matInput [ngModel]="currentNode" (ngModelChange)="currentNode.name = $event"  [matAutocomplete]="auto"/>

<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
  <mat-option *ngFor="let option of searchResults" [value]="option">
    {{getHints(option)}}
  </mat-option>
</mat-autocomplete>

<li *ngFor="let item of currentNode.parameters; index as i;">
  <br />
  <input [ngModel]="item.name" (ngModelChange)="item.name = $event" (focus)="onParameterFocus(i)" (blur)="onParameterBlur()" />
  <input [ngModel]="item.value" (ngModelChange)="item.value = $event" (focus)="onParameterFocus(i)" (blur)="onParameterBlur()" />
  <br />
</li>


Свойство currentNode, которое находится в дочернем компоненте, имеет идентификатор, имя, параметры и т. д., и activeElement также должен иметь их. Я имею в виду, что при изменении currentNode, activeElement тоже должен изменяться. Речь идет о привязке данных. Но я не понимаю, как это сделать правильно. Я хочу, чтобы каждый раз, когда изменяется currentNode, activeElement также менялся (я имею в виду, что это должны быть две одинаковые переменные, когда дело доходит до изменения currentNode).
  • Вопрос задан
  • 50 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы