angular передача данных от дочернего элемента к родительскому без дочернего тега - PullRequest
3 голосов
/ 04 августа 2020

Я пытаюсь передать данные от дочернего к родительскому, передавая, но у меня нет дочернего тега, а go дочернему элементу только с маршрутом, так как же можно прослушивать отправку данных?

parent. html

<ul class="list-unstyled multi-steps">
    <li [ngClass]="{ ' is-active': status == 'first' }">
        <span routerLink="/room/specification"></span>
              step1
    </li>
    <li [ngClass]="{ ' is-active ': status == 'second' }">
         <span routerLink="/room/attributes" (click)="onClick()"></span>
              step2
    </li>
</ul>
<div class="content">
    <router-outlet></router-outlet>
</div>

спецификация-child.ts

 @Output("specificationData") specificationData = new EventEmitter();

     onSubmit() {
      const data = { this.specificationForm.value };
      this.specificationData.emit(data);
     }

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

<child (specificationData)="getData($event)"></child>

и что мне делать?

Ответы [ 4 ]

1 голос
/ 04 августа 2020

В этом случае вместо EventEmitter вы можете использовать одноэлементную службу, которая разделяет переменную между родительским и дочерним.

shared.service.ts

@Injectable({ providedIn: 'root' })
export class SharedService {
  private specDataSource = new ReplaySubject<any>(1);
  public specData$ = this.specDataSource.asObservable();

  public setSpecData(data: any) {
    this.specDataSource.next(data);
  }
}

Я использовал ReplaySubject(1), который может буферизовать / хранить последнее значение и выдавать его сразу после подписки. Вы также можете использовать Rx JS Subject или BehaviorSubject в соответствии с вашими требованиями.

спецификация-child.ts

constructor(private shared: SharedService) { }

onSubmit() {
  this.shared.setSpecData({ this.specificationForm.value });
}

parent .ts

specData: any;
complete$ = new Subject<any>();

constructor(private shared: SharedService) { }

ngOnInit() {
  this.shared.specData$.pipe(
    takeUntil(this.complete$)   // <-- use to close the subscription
  ).subscribe(data => this.specData = data);
}

ngOnDestroy() {
  this.complete$.next();        // <-- close impending subscriptions
}
0 голосов
/ 04 августа 2020

Вы можете использовать EventEmitter или Subject. В таких случаях рекомендуется использовать тему.

Вы можете использовать сервис для обмена передаваемыми значениями:

import {Injectable, EventEmitter} from '@angular/core';
import { Subject } from 'rxjs';

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

  }

  public emitter: Subject<string> = new Subject<string>(); // Subject
 // public emitter : EventEmitter<string> = new EventEmitter(); // Event Emitter
 
  getEmittedValue() {
    return this.emitter;
  }

Ваш образец дочернего шаблона:

<button (click)="go('From Child')">Emit</button>

Ваш образец дочернего компонента ( Не забудьте внедрить службу, которую я создал выше):

go(message: string) {
    console.log('Button Clicked ', message);
    this.appService.emitter.next(message); // Subject
   // this.appService.emitter.emit();  // Event Emitter
  }

Теперь пора где угодно использовать выводимые данные дочернего компонента. Просто введите сервис, который я создал выше, в любое место, где вы хотите, чтобы выдаваемое значение было выдано, и подпишитесь на Subject или Event Emitter:

constructor(private appsService: AppService) {
    this.appsService.getEmittedValue().subscribe(res => this.ekMethod(res));
  }
0 голосов
/ 04 августа 2020

In Angular 7.2.0 +

parent.component.ts

    <ul class="list-unstyled multi-steps">
    <li [ngClass]="{ ' is-active': status == 'first' }">
        <span [routerLink]="/room/specification" [state]="{data: {...}}"></span>
              step1
    </li>
    <li [ngClass]="{ ' is-active ': status == 'second' }">
         <span [routerLink]="/room/attributes"  [state]="{data: {...}}"(click)="onClick()"></span>
              step2
    </li>
</ul>
<div class="content">
    <router-outlet></router-outlet>
</div>

specificatioon.child.ts

Получение данные не так очевидны на первый взгляд. Кто-то мог ожидать, что ActivatedRoute будет содержать его, но для состояния нет атрибута. Свойство состояния было добавлено в навигацию, доступную через Router.getCurrentNavigation (). Extras.state. Проблема в том, что getCurrentNavigation возвращает Navigation только во время навигации и возвращает null после завершения навигации. Таким образом, навигация больше не доступна в хуке жизненного цикла onInit компонента B. Нам нужно прочитать данные из объекта истории браузера:

history.state.data
0 голосов
/ 04 августа 2020

Одним из решений этой проблемы может быть использование Angular Services. Обратитесь к документации , чтобы узнать о них больше.

И в службе вы можете использовать EventEmitter, но по соглашению следует использовать Rx JS Subjects . Вы можете создать экземпляр объекта в службе и использовать его для передачи данных из одного компонента в любой другой компонент.

Пример службы будет выглядеть так:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class DataService {
  dataSubject = new Subject<TypeOfData>();

  constructor() { }

}

, а затем, в дочернем компоненте вы можете использовать Dependency Injection для доступа к экземпляру службы и передачи данных изнутри.

  constructor(private dataService: DataService) {}

  onSubmit() {
    const data = { this.specificationForm.value };
    this.dataService.dataSubject.next(data);
  }

, а затем просто иметь подписку на тему в родительском компоненте:

  constructor(private dataService: DataService) {}

  ngOnInit() {
    this.dataService.dataSubject.subscribe(data => {
      // Do something with the data
    });
  }

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...