Angular - How to invoke function from parent to child component - javascript

I have this situation: A parent component structured in this way:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-parent',
templateUrl: './parent.component.html',
styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
with this html (parent has an ng-content):
<div>
<ng-content></ng-content>
<button>Click to say Hello!!!</button>
</div>
and a child component like this:
import { Component, OnInit } from "#angular/core";
#Component({
selector: "app-child",
templateUrl: "./child.component.html",
styleUrls: ["./child.component.css"]
})
export class ChildComponent implements OnInit {
onSubmit() {
alert("hello");
}
constructor() {}
ngOnInit() {}
}
with this html:
<div>I'm child component</div>
From the parent component I want to click inside button to invoke onSubmit child function...is this possible?
<app-parent>
<app-child>
</app-child>
</app-parent>
This is a sample; I'm creating a modal that has default buttons: "CANCEL" and "SUCCESS". On the success button I need to invoke one function declared into the childrenComponent.
This is the stackblitz example: https://stackblitz.com/edit/angular-ivy-vuctg4

You can access like that
app.component.html
<hello name="{{ name }}"></hello>
<app-parent (clickActionCB)="clickActionCB($event)">
<app-child></app-child>
</app-parent>
app.component.ts
import { Component, VERSION, ViewChild } from "#angular/core";
import { ChildComponent } from "./child/child.component";
#Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
name = "Angular " + VERSION.major;
#ViewChild(ChildComponent) childRef: ChildComponent;
clickActionCB(eventData) {
this.childRef.onSubmit() ;
}
}
parent.component.ts
import { Component, EventEmitter, OnInit, Output } from "#angular/core";
#Component({
selector: "app-parent",
templateUrl: "./parent.component.html",
styleUrls: ["./parent.component.css"]
})
export class ParentComponent implements OnInit {
constructor() {}
ngOnInit() {}
#Output() clickActionCB = new EventEmitter<string>();
clickAction() {
this.clickActionCB.emit();
}
}
parent.component.html
<div>
<ng-content></ng-content>
<button (click)="clickAction()">Click to say Hello!!!</button>
</div>
Live stackblitz URL

child.component.ts
import { Component, OnInit } from "#angular/core";
#Component({
selector: "app-child",
template: `
<div>I'm child component</div>
`
})
export class ChildComponent implements OnInit {
onSubmit() {
alert("hello");
}
constructor() {}
ngOnInit() {}
}
parent.component.ts
import { ChildComponent } from "../child/child.component";
#Component({
selector: "app-parent",
template: `
<div>
<ng-content></ng-content>
<button (click)="onClick()">Click to say Hello!!!</button>
</div>
`
})
export class ParentComponent implements OnInit {
#ContentChild(ChildComponent) childRef: ChildComponent;
constructor() {}
ngOnInit() {}
onClick() {
this.childRef.onSubmit();
}
}
https://stackblitz.com/edit/angular-ivy-mteusj?file=src%2Fapp%2Fparent%2Fparent.component.ts

Related

How to update other component html text value

This is my app.component.html source code:
<split-flap></split-flap>
<button (click)="flip('+')">+</button><button (click)="flip('-')">-</button>
This is my app.component.ts source code:
import { Component } from '#angular/core';
import { SplitFlapComponent } from './split-flap/split-flap.component';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers:[SplitFlapComponent]
})
export class AppComponent {
constructor(private splitFlapComponent: SplitFlapComponent)
{
}
flip(flag)
{
console.log(flag);
this.splitFlapComponent.title=flag;
}
}
This is my split-flap.component.ts:
import { Component, OnInit, Input, Output } from '#angular/core';
#Component({
selector: 'split-flap',
templateUrl: './split-flap.component.html',
styleUrls: ['./split-flap.component.css']
})
export class SplitFlapComponent implements OnInit {
title: string;
constructor() {
this.title = 'split-flap works1!';
}
ngOnInit() {
}
}
This is my split-flap.component.html:
<p>{{title}}</p>
My app.component.html has two buttons, both of them pass a sign to split-flap.component, would you tell me how can I the update split-flap.component.html content? Because most of the examples for input box only, I cannot find an example for <p>.
Try like this:
Solution 1 : #Input()
app.component.html
<split-flap [title]="title"></split-flap>
app.component.ts
title: string;
constructor() {
this.title = 'split-flap works1!';
}
flip(flag)
{
console.log(flag);
this.title=flag;
}
split-flap.component.ts:
#Input() title: string
Solution 2 : ViewChild()
app.component.html
<split-flap #child ></split-flap>
app.component.ts
#ViewChild('child') child: SplitFlapComponent ;
flip(flag)
{
console.log(flag);
this.child.title=flag;
}

Angular Child Component is not being rendered as parent data changes

Below code I have method to select hero and it is updating selectedHero of app.component but after updating detail.component is not being rerendered.
please let me know how to notify child component when parent data changes.
app.component.ts
import { heroes } from './Hero.service';
import { Component, OnInit } from '#angular/core';
import {Hero} from './Hero'
import { heroes } from './Hero.service';
import { Component, OnInit } from '#angular/core';
import {Hero} from './Hero'
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'tour-of-heroes';
Heroes:Hero[]=heroes;
selectedHero:Hero;
constructor(){
}
selectHero(hero){
this.selectedHero = hero;
console.log(this.selectedHero)
}
}
master.component.ts
import { Hero } from './../Hero';
import { Component, OnInit, Input, Output} from '#angular/core';
import { EventEmitter } from 'protractor';
#Component({
selector: 'app-master',
templateUrl: './master.component.html',
styleUrls: ['./master.component.scss']
})
export class MasterComponent implements OnInit {
#Input() Heroes:Hero[];
#Input() selectHero;
constructor() { }
ngOnInit() {
console.log(this.Heroes,'master Heroes')
}
}
details.component.ts
import { Hero } from './../Hero';
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'app-detail',
templateUrl: './detail.component.html',
styleUrls: ['./detail.component.scss']
})
export class DetailComponent implements OnInit {
#Input() selectedHero:Hero;
constructor() { }
ngOnInit() {
console.log(this.selectedHero)
}
}
app.component.html
<div style="text-align:center">
<h1>Tour of Heroes</h1>
<div class="Layout">
<app-master [Heroes]="Heroes" [selectHero]="selectHero"></app-master>
</div>
<div class="Layout">
<app-detail [selectedHero]="selectedHero"></app-detail>
</div>
</div>
master.component.html
<div class="master">
<ul>
<li *ngFor="let hero of Heroes" (click)="selectHero(hero)">
<span>
Id : {{hero.id}}
</span>
<br/>
<span>
Name : {{hero.name}}
</span>
</li>
</ul>
</div>
detail.component.html
<div *ngIf="selectedHero">
<h3>Selected Hero is : {{selectedHero.name}} </h3>
<div>
<p>Id : {{selectedHero.id}}</p>
<p>Name : {{selectedHero.name}}</p>
</div>
</div>
In app.compponent selectedHero is being passed to details-component.
In DetailComponent, Data changes from parent component will be handled on ngOnChanges Life Cycle Hook.
export class DetailComponent implements OnInit, OnChanges {
#Input() selectedHero:Hero;
constructor() { }
ngOnInit() {
console.log(this.selectedHero)
}
ngOnChanges() {
console.log(this.selectedHero)
}
}

html wont render from inside angular 2 component

I'm using a service to dynamically change the content in my header depending on the page I'm on, however when I put HTML in my component it doesn't render in the browser (see example below)
home.component.ts
import { Component, OnInit } from '#angular/core';
import { HeaderTitleService } from '../../services/headerTitle.service';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
constructor(
private headerTitleService: HeaderTitleService
) { }
ngOnInit() {
this.headerTitleService.setTitle(`
We strive to create things
<br> that are engaging, progressive
<br> & above all
<span class="highlight">
<em>innovative.</em>
</span>
`);
}
}
header.component.ts
import { Component, OnInit } from '#angular/core';
import { HeaderTitleService } from '../../../services/headerTitle.service'
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {
title: any;
constructor(
private headerTitleService: HeaderTitleService
) { }
ngOnInit() {
this.headerTitleService.title.subscribe(updatedTitle => {
this.title = updatedTitle;
});
}
}
header.component.html
<h1>{{title}}</h1>
so Im trying to set the title to be a string that has html tags in it that I want to be rendered but what happens is the whole thing comes out as a string instead of how it would look like it I had put it in my home.component.html.
Is there a way I can do this??
You can set the [innerHtml] property
<h1 [innerHtml]="title"></h1>
Example

Javascript Angular 4 eventEmitter with ngClass

I am using Angular 4 and eventEmitter to change a class name.
The class css is:
.paintRed {
background-color: red;
}
Now for the Angular part:
I have a button component:
button.compoment.ts:
import { Component, OnInit, Output, EventEmitter } from '#angular/core';
#Component({
selector: 'app-button',
templateUrl: './button.component.html',
styleUrls: ['./button.component.scss']
})
export class ButtonComponent implements OnInit {
#Output() outputEvent: EventEmitter<any> = new EventEmitter();
constructor() { }
ngOnInit() {}
sendOutEvent() {
this.outputEvent.emit('paintRed');
}
}
button.component.html
<p (click)="sendOutEvent()">Click to Emit</p>
Finally on my app.component.ts I have:
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'app';
handleEvent(value) {
console.log(value);
document.getElementById('elementId').classList.add(value);
}
}
and my app.component.html looks like this:
<div id="elementId">
<app-button (outputEvent)="handleEvent($event)"></app-button>
</div>
The above will successfully add the class "paintRed" to elementId but what I want to do is this:
<div ngClass="myClass">
<app-button (outputEvent)="handleEvent($event)"></app-button>
</div>
Basically I want to use ngClass to change the value sent by handleEvent($event) ...
How can I do that?
In your app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'app';
myClass = '';
handleEvent(value) {
console.log(value);
myClass = value;
}
}
And your html:
<div [ngClass]="myClass">
<app-button (outputEvent)="handleEvent($event)"></app-button>
</div>

ng2 [disabled]="!myInput.value" doesnt work correctly

I'm building a standard angular2 app(more specific a todo app). I also added #Ngrx/store.
The first time I load the page, the button is disabled, but when I enter some value in the input box, the button needs to be enabled, but it stays disabled...
app/app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
template: `
<h1>Hello {{name}}</h1>
<div>
<add-todo></add-todo>
</div>`,
})
export class AppComponent { name = 'Angular'; }
app/components/add-todo/add-todo.component.ts
import { Component, ViewChild, ElementRef } from '#angular/core';
#Component({
moduleId: module.id,
selector: 'add-todo',
template: `
Create new todo
<input #myInput />
<button (click)="addTodo()" [disabled]="!myInput.value">Add</button>`
})
export class AddTodoComponent {
#ViewChild('myInput') input: ElementRef;
constructor() {}
addTodo(): void {
alert(this.input.nativeElement.value);
}
}
From the documentation https://angular.io/docs/ts/latest/guide/forms.html Track the change state and validity of form controls using ngModel...
Update your code to use ngModel and it should work as expected
import { Component, ViewChild, ElementRef } from '#angular/core';
#Component({
moduleId: module.id,
selector: 'add-todo',
template: `
Create new todo
<input #myInput [(ngModel)]="inputFieldValue" />
<button (click)="addTodo()" [disabled]="!myInput.value">Add</button>`
})
export class AddTodoComponent {
#ViewChild('myInput') input: ElementRef;
public inputFieldValue:string = '';
constructor() {}
addTodo(): void {
alert(this.input.nativeElement.value);
}
}
What if you do this way:
import {Component} from '#angular/core';
#Component({
selector: 'add-todo',
template: `
Create new todo
<input #todoTitleInput [(ngModel)]="todoTitle"/>
<button (click)="addTodo(todoTitleInput.value)" [disabled]="!todoTitle">Add</button>
`,
})
export class AddTodoComponent {
addTodo(title: string): void {
alert(title);
}
}

Categories

Resources