Angular 8 - в моем простом примере ViewChild () работает только с массивом, но не с переменной - PullRequest
0 голосов
/ 26 марта 2020

Как мне заставить это работать: у меня есть дочерний компонент с полем ввода и кнопкой ОТПРАВИТЬ. При нажатии значение должно быть отображено в родительском компоненте.

Эта настройка работает: дочерний компонент имеет вход, который использует двойное связывание ngModel для строки. Кнопка запускает функцию, которая помещает текущее значение поля ввода в массив. Родительский компонент использует ViewChild () и через * ngFor l oop каждое новое значение отображается в списке.

Как я могу реализовать это без массива, а только с одной переменной значения? Закомментированный код (для настройки массива) работает. Stackblitz: https://stackblitz.com/edit/ng8child2parentviewchildtest?embed=1&file=src / app / app.component.ts

Любая помощь приветствуется, спасибо.

Child Component
template:
<input type="text" [(ngModel)]="currentMsgToParent">
<button (click)="msgToParent()">send</button>

.ts:
export class Child1Component {
  name = 'Child';

  currentMsgToParent = '';
  // msgFromChild1 = []

  msgToParent() {
    this.currentMsgToParent;
    // this.msgFromChild1.push(this.currentMsgToParent);
  }
}

parent component:
template:
<div class="child1">
  <p><b>Message from Child</b><br> via ChildView():</p>
  <p>{{ currentMsgToParent }}</p>
  <!-- <ul *ngFor="let item of msgFromChild1">
    <li>{{ item }}</li>
  </ul> -->
  <hr>
  <app-child1></app-child1>
</div>

ts.:
export class AppComponent implements AfterViewInit {
  @ViewChild(Child1Component, {static: false}) child1: Child1Component;

  name = 'Parent';
  msgFromChild1: any;
  currentMsgToParent = '';

  ngAfterViewInit() {
    this.currentMsgToParent = this.child1.currentMsgToParent;
    // this.msgFromChild1 = this.child1.msgFromChild1;
  }
}

Ответы [ 2 ]

1 голос
/ 27 марта 2020

Проблема в том, что вы обновляете значение в родительском компоненте только один раз, в ngAfterViewInit:

ngAfterViewInit() {
  this.currentMsgFromChild = this.child1.currentMsgToParent;
}

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

С другой стороны, когда свойство родительского компонента установлено в массив дочернего компонента, оба свойства ссылаются на один и тот же массив. Когда массив изменяется, два компонента могут получить доступ к обновленным значениям. Вы бы имели такую ​​же ситуацию, если бы два компонента совместно использовали ссылку на объект, а дочерний ввод был связан со свойством этого объекта (см. this stackblitz ).

Стандартным способом обновления родительского элемента является привязка события со свойством @Output, но если вы хотите обратиться непосредственно к дочернему компоненту в коде, вы можете определить свойство родительского компонента как получатель. Это обеспечит актуальность отображаемого в представлении значения.

get currentMsgFromChild() {
  return this.child1 ? this.child1.currentMsgToParent : "";
}

См. этот стек * блиц для демонстрации.

0 голосов
/ 27 марта 2020

Нет способа использовать ViewChild внутри ваших ngFor l oop в Html файлах. Но есть и другой способ сделать что-то похожее на это. Вы можете использовать Directives, а внутри них использовать ViewChild. Вы можете создать Directive, используя ng generate directive directive_name и использовать ViewChild внутри него. Вы также можете передать некоторые атрибуты этой директиве так же, как и с компонентами. Но чтобы использовать ViewChild, вам нужно inject elementRef с помощью конструктора:

constructor(private elementRef: ElementRef)

будет inject it.

...