#javascript #angular #parameter-passing #angular-event-emitter
#javascript #angular #передача параметров #angular-event-эмиттер
Вопрос:
Мне нужно передать значение ввода из дочернего компонента в родительский компонент, когда пользователь нажимает кнопку отправки, которая существует в родительском компоненте.
Шаблон дочернего компонента
<input
type="password"
[(ngModel)]="userPasswordForm.inputId"
class="mr-password-field k-textbox"
/>
Файл TS дочернего компонента
export class PasswordInputComponent{
constructor() { }
@Output() inputValue = new EventEmitter<string>();
userPasswordForm:any={'input':''};
emitValue(value: string) {
this.inputValue.emit(value);
}
}
Шаблон родительского компонента
<child-component (inputValue)="" > </child-component>
<button (click)="getValueFromChild()"> </button>
Файл TS родительского компонента
tempUserFormPasswords:any=[];
.
.
.
getValueFromChild(receivedVal){
this.tempUserFormPasswords.push(receivedVal);
}
Это было бы легко сделать, если кнопка существует внутри дочернего компонента. но в этом случае значение должно передаваться при нажатии кнопки в родительском компоненте!
Комментарии:
1. Я не понимаю, пожалуйста. Вы хотите поместить значение в
tempUserFormPasswords
массив при нажатии наgetValueFromChild
родительский компонент, но передаваемое значение поступает из дочернего компонента?
Ответ №1:
Для одного дочернего компонента: используйте ViewChild
Для использования нескольких дочерних компонентов: ViewChildren
Файл TS родительского компонента
Один дочерний компонент:
tempUserFormPasswords:any=[];
@ViewChild(ChildComponent) child: ChildComponent;
.
.
.
getValueFromChild(receivedVal){
var data = child.getData();
this.tempUserFormPasswords.push(data);
}
Несколько дочерних компонентов:
tempUserFormPasswords:any=[];
@ViewChildren(ChildComponent) child: ChildComponent;
@ViewChildren(ChildComponent) children: QueryList<ChildComponent>;
.
.
.
getValueFromChild(receivedVal){
let data;
children.forEach(child => (data = this.updateData(child.data));
this.tempUserFormPasswords.push(data);
}
Комментарии:
1. похоже, это работает только тогда, когда я импортирую дочерний компонент только один раз в родительский компонент, если я импортировал его два раза несколько раз, другие значения из других дочерних входных данных были бы неопределенными, могу я знать, почему?
2. если вам нужно использовать два или более компонентов, вы должны использовать
@ViewChildren
, вместо этого! Проверьте документы Angular.3. Согласен с @GBra относительно
@ViewChildren
4. не могли бы вы обновить свой ответ? и я обновлю вопрос
5. конечно, ожидание обновления вопроса, чтобы оно лучше отражало решение
Ответ №2:
Создайте объект BehaviorSubject в файле service
@Injectable()
export class dataService {
data: BehaviorSubject<any> = new BehaviorSubject<any>(null);
public setData(data: any){
this.data.next(data);
}
public getData(): Observable<any> {
return this.data.asObservable();
}
}
Вам необходимо подписаться на данные в вашем дочернем компоненте
PasswordInputComponent
export class PasswordInputComponent{
constructor(private service: dataService) {
this.service.getData().subscribe((data) => {
//Emit the event here
this.inputValue.emit(value);
});
}
@Output() inputValue = new EventEmitter<string>();
userPasswordForm:any={'input':''};
emitValue(value: string) {
this.inputValue.emit(value);
}
}
ParentComponent.ts
tempUserFormPasswords:any=[];
.
.
.
constructor(private service: dataService) { }
getValueFromChild(receivedVal){
this.service.setData('');
this.tempUserFormPasswords.push(receivedVal);
}
Когда кнопка нажата на родительском компоненте, мы устанавливаем субъект поведения данных, когда к нему добавляется новое значение, оно автоматически подписывается на дочерний компонент component.so , в это время нам нужно выдать событие.
Я думаю, это вам поможет..
Комментарии:
1. Мне нравится этот блог, в котором объясняется 4 способа связи от родителя к потомку. Эта форма, которую вы называете служебной. Но иногда кажется, что это должно быть проще fireship.io/lessons /…
Ответ №3:
Читайте о декораторах ввода и вывода в angular!
документация: совместное использование данных.
Примеры: примеры
Ответ №4:
Вы можете сделать это с помощью ViewChild, как уже было сказано в другом ответе от @Raz Ronen. Но имейте в виду, что в зависимости от версии Angular вам может потребоваться дождаться выполнения перехвата жизненного цикла AfterViewInit для взаимодействия с дочерним элементом (или дочерний элемент не будет доступен, поскольку он не инициализирован).
Кроме того, вы можете сделать это с помощью BehaviorSubject , как только что ответил @Msk Satheesh , и это тоже прекрасно. Но это может показаться немного излишним для такого простого варианта использования. (это то, что мы обычно делаем, когда у нас нет связи между компонентами, например, один компонент не является дочерним элементом другого)
То, что я предлагаю, я считаю самым простым из всех (опять же, их ответы ни в коем случае не плохие); Это в основном то же самое, что и @Msk Satheesh (но под капотом), только немного более угловатый стиль: Output EventEmitter:
Родительский компонент:
import { Component } from '@angular/core';
@Component({
selector: 'app-parent',
template: `
Message: {{message}}
<app-child (messageEvent)="receiveMessage($event)"></app-child>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent {
constructor() { }
message:string;
receiveMessage($event) {
this.message = $event
}
}
Дочерний компонент:
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<button (click)="sendMessage()">Send Message</button>
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
message: string = "a string from child component"
@Output() messageEvent = new EventEmitter<string>();
constructor() { }
sendMessage() {
this.messageEvent.emit(this.message)
}
}
С помощью кода родительский компонент всегда будет подписан на MessageEvent, который выводится дочерним компонентом, и он будет запускать функцию (функцию сообщения) после отправки дочернего компонента. Обработка этого с помощью Angular имеет то преимущество, что мы уверены, что у нас нет утечки памяти в нашем приложении (например, отсутствие отписок).
Когда прослушивающий компонент (подписанный родительский компонент) будет уничтожен, Angular автоматически откажется от подписки, чтобы избежать потенциальных утечек памяти.
Комментарии:
1. Спасибо за ваш ответ, но это не тот случай, который я хочу, так как мне нужно, чтобы кнопка была нажата в родительском компоненте, как функция в родительском компоненте под названием «ReceiveMessage» при нажатии на нее она получает значение из дочернего компонента
2. Я не уверен, что понимаю, «поскольку мне нужно, чтобы кнопка была нажата в родительском компоненте, как функция в родительском компоненте, называемая «ReceiveMessage», при нажатии на нее она получает значение из дочернего компонента». Поэтому я не уверен, чем могу вам помочь. Все ответы, которые я упомянул в своем ответе, делают одно и то же: они позволяют обмениваться данными от дочернего элемента к родительскому. Если вам нужно обратное (от родителя к потомку), вы можете просто использовать
input()
вместоoutput()
и безeventEmitter
.3. Мне действительно нужно передавать данные от дочернего компонента к родительскому, но в приведенном вами примере вы выполняете функцию в дочернем компоненте, которая срабатывает при нажатии. Я хочу сделать это таким же образом, но кнопка существует в родительском компоненте.
4. вы можете сделать это с помощью ввода вывода и источника событий. вы передаете необходимые данные от родительского компонента к дочернему с
input()
помощью, затем по щелчку вы следуете примеру. Но если вы предпочитаете делать это с@viewChild
помощью или@viewChildren
, просто сделайте это таким образом. Это действительно то же самое, пока ваши дочерние методы являются общедоступными, их можно использовать из родительского компонента без каких-либо проблем.