简体   繁体   中英

Angular pass input variable to another component on button click

I come from a Python background, but I started trying to learn Angular and I'm really having trouble. Working between components is confusing to me and I can't figure it out. I made a good example that I think if someone helped me with it would go along way towards understanding Angular.

I just have two components: a "header" component and an app component. In the header component, I ask for the user's name and they click a button, and then it should show "Hello {{name}}" in the next component. I cannot get it to work to say the least and it's really frustrating. The Header part seems to work okay, but it's just not communicating with the other component at all. Neither the button part or the "name" part are working so I am clearly misunderstanding something I need to do when it comes to listening from the parent component.

Here is my Header HTML:

Name: <input type="text" id="userInput" value="Joe">

<button (click)=showName()>Show More</button>

Here is my Header TS:

import { Component, OnInit, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
  bodyDiv = false;
  inputName = '';
  @Output() buttonClicked = new EventEmitter();

  constructor() { }

  ngOnInit() {
  }
  showName() {
    console.log('showName clicked.');
    this.bodyDiv = true;
    this.inputName = document.getElementById('userInput').value;
    console.log(this.inputName);
    console.log(this.bodyDiv);
    this.buttonClicked.emit(this.bodyDiv);
    this.buttonClicked.emit(this.inputName);
  }
}

Here is the main Component's HTML:

<app-header (buttonClicked)='showNextComponent($event)'></app-header>

<p *ngIf="![hiddenDiv]" [inputName]="name">Hello {{ name }} </p>

Here is the main component's TS:

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  hiddenComponent = true;
  title = 'show-button';

  showNextComponent() {
    console.log('Button clicked.');
    this.hiddenComponent = false;
    console.log(this.hiddenComponent);
  }
}

So who can show me what I'm doing wrong and help figure out Angular a little better? :) Thank you!

replace showName function with below code :

 showName() { console.log('showName clicked.'); this.bodyDiv = true; this.inputName = document.getElementById('userInput').value; console.log(this.inputName); console.log(this.bodyDiv); this.buttonClicked.emit(this.inputName); } 
replace below code in your main component.

 name:string showNextComponent(value:string) { this.name = value; } 

replace below code in your html :

 <app-header (buttonClicked)='showNextComponent($event)'></app-header> <p *ngIf="name">Hello {{ name }} </p> 

Please let me if you have any question and I would suggest try to use ngmodel or something else instead of directly communicating with the DOM.

Here is a slightly modified and working sample: https://stackblitz.com/edit/angular-jhhctr

The event emitter in the header component emits the name (string) which is the $event in showNextComponent($event) . You have to capture this in the main component and assign it to a local variable to be able to use it in the main component's template as {{name}}

[inputName]="name" is incorrect. You can pass values like that to angular components not to actual HTML DOM elements.

There are couple of ways to communicate from one component to another in angular - Using @Input() in your child component will expects an input from parent component and @Output() from your child component will emit an event from the child component

So in your case if you want to pass a value from parent to child you need to use input property or decorator on your child property - I will provide you the code but just go through proper guidance from the link provided this will make you to create better angular applications https://angular.io/guide/component-interaction

First you need to swap your components your header component should be your parent and the child component will be your main component - if you want to work in the same way just move your codes vice versa

Header html

    Name: <input type="text" id="userInput" name='userInput' [(ngModel)]='inputName' value="Joe">

    <button (click)=showName()>Show More</button>
    <div [hidden]='bodyDiv'>
      <app-header [bindName]='inputName'></app-header>
    </div>

Header Component

import { Component, OnInit, Output, EventEmitter } from '@angular/core';

    @Component({
      selector: 'app-header',
      templateUrl: './header.component.html',
      styleUrls: ['./header.component.css']
    })
    export class HeaderComponent implements OnInit {
      bodyDiv = true;
      inputName = '';


      constructor() { }

      ngOnInit() {
      }
      showName() {
        bodyDiv = false;
      }
    }

Main Component Html

<p>Hello {{ bindName }} </p>

Main component ts

import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  @Input()
  bindName: string;

}

In your header component the inputName property will be binded using two way data binding where i used [(ngModel)]='inputName' so whatever you enter in the input text it will be updated in your inputName property

Now we need to do only one thing just to show your child component with any event - so when the button is clicked the div with [hidden] property will be false and it will be displayed and as we pass the inputName to the child Component it will be updated

And finally the child component will be displayed and the input written in the text will be updated in the child component - when the child component html displays the bindName will be updated and there will be result you expected

That's all I think this should work well - Try this and let me know - Thanks Happy coding !!

Don't forget to look into the link above where you can see many types of component interactions

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM