How to call a component from other component in angular 7 - html

I have a checkbox,if that checkbox is checked, I need to show alert message on load the application.But problem is that checkbox is in header component and it is linked with home component.So when I will be in home page and if that checkbox is checked, I need to show alert message on load the application. Here is the code below,
header.component.html
<div><input checked type="checkbox">Other-component</div>
header.component.ts
import { Component, OnInit } from '#angular/core';
import { Router } from "#angular/router";
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
constructor(public router: Router){}
ngOnInit() {}
}
home.component.ts
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup, Validators } from '#angular/forms';
import Speech from 'speak-tts';
import { RxSpeechRecognitionService, resultList, } from '#kamiazya/ngx-speech-recognition';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css'],
providers: [ RxSpeechRecognitionService ]
})
export class HomeComponent implements OnInit {
showit:any;
nestedjson:any;
constructor(private formBuilder: FormBuilder,public service: RxSpeechRecognitionService) {
}
ngOnInit() {
}
}

1) To the question in your headline: How to call a component from other component
You can give the header component a reference id inside the home template.
<app-header #header></app-header>
Then you can access the header component through a ViewChild in your home component.
#ViewChild('header') headerComponent: HeaderComponent;
But this does not seem to be very good practice for your needs. Consider using a service and subscribe to a Subject by using RxJs Observables. Or much simpler in your case: just use two-way-data-binding.
2) The way you should actually communicate between components: two way data binding
header.component.ts
export class HeaderComponent implements OnInit {
#Input() isChecked: boolean;
#Output() isCheckedChanged = new EventEmitter<boolean>();
constructor(public router: Router){}
ngOnInit() {
}
}
header.component.html
<input [(ngModel)]="isChecked" type="checkbox">
home.component.ts
export class HomeComponent implements OnInit {
isChecked: boolean;
constructor() {}
ngOnInit() {
}
}
home.component.html
<app-header [(isChecked)]="isChecked"></app-header>
Edit: in your case you also don't need two way binding since you don't need any feedback from the HeaderComponent. One way data binding will be fine. Then you can remove the line
#Output() isCheckedChanged = new EventEmitter<boolean>();
And in Home template don't use banana in the box syntax [()], instead just use []:
<app-header [isChecked]="isChecked"></app-header>

You can make use of a service which is defined at the root level.And then with the help of a service you can either emit or use Subjects to capture in your home component.

Related

Angular: sanitizer.bypassSecurityTrustHtml does not render attribute (click)

I try to render a button and it works fine, but when I click the button it doesn't execute alertWindow function, help!:
app.component.ts:
import {
Component,
ElementRef,
OnInit,
ViewEncapsulation } from '#angular/core';
import { DomSanitizer, SafeHtml } from "#angular/platform-browser";
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
encapsulation: ViewEncapsulation.ShadowDom,
})
export class AppComponent implements OnInit {
public content: SafeHtml;
constructor(private sanitizer: DomSanitizer) {}
async ngOnInit() { this.renderButton(); }
alertWindow() { alert("don't work"); }
renderButton() {
this.content =
this.sanitizer.bypassSecurityTrustHtml(`
<button (click)='connectWallet()' class="button">
Connect your wallet
</button>`);
}
app.component.ts;
<div [innerHTML]="content"></div>
Solution
Based on what I understand you wanted to display HTML dynamically at runtime? then solution is to use
ComponentFactoryResolver
and ViewContainerRef
It will be better if you can provide more details, what you are trying to achieve, so that people can guide you
Why it didn't work?
It doesn't work because it is outside of angular, when you use innerHTML then whatever you passed to it is pure vanilla HTML and JavaScript
Try this example
(window as any).alertWindow = function () {
alert("don't works");
};
#Component({...})
export class AppComponent {
...
renderButton() {
this.content = this.sanitizer.bypassSecurityTrustHtml(`
<button onclick='alertWindow()' class="button">Connect your wallet</button>
`);
}
}
It works right?
As you can see I have moved alrertWindow function outside of component's class and added to window variable and also changed (click) to onclick

How to get the selected value from one component to other using event emitter in angular 8

I have 2 components , one login and other home. When I change drop down into login component ,selected value need to display in home component. I am already emitting the onchange event from login component to home component and displaying the value but still I am not getting the value into home component.Here is the code below
login.component.html
<select #mySelect (change)="onOptionsSelected(mySelect.value)">
<option value="one">one</option>
<option value="two">two</option>
</select>
login.component.ts
import { Component, OnInit,Input,Output, EventEmitter } from '#angular/core';
import { Router } from '#angular/router';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
#Output() buttonClicked = new EventEmitter();
constructor(private router: Router) { }
#Input() item: string;
ngOnInit() {
}
onOptionsSelected(value:string){
console.log("the selected value is " + value);
this.buttonClicked.emit(value);
this.router.navigateByUrl('/home');
}
}
home.component.html
<p>home works!</p>
<app-login (buttonClicked)='showNextComponent($event)'></app-login>
<p>Hello {{ name }} </p>
home.component.ts
import { Component, OnInit,ElementRef,ViewChild } from '#angular/core';
import { CommonserviceService } from './../utilities/services/commonservice.service';
import { LoginComponent } from '../login/login.component';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
getListData: any;
constructor(private commonserviceService: CommonserviceService) { }
name:string
ngOnInit() {
}
showNextComponent(value:string) {
this.name = value;
console.log(this.name);
}
}
I pasted your code here in stackblitz: https://stackblitz.com/edit/angular-cfkqns
You are correctly emitted values up to the parent component and binding the value to be displayed in the parent component.
It is working how you expect it to :-)
UPDATE:
I have answered the same question for some one else here:
https://stackoverflow.com/a/64082745/450388
however I have updated your stackblitz to reflect how to achieve the same.
https://stackblitz.com/edit/angular-cfkqns

Cannot access the parent formControl object changes in a Parent-Child Component relationship in Angular 8

I have created a parent component as follows:
<form [formGroup] = "cardForm">
<app-inputvalidator [controls] = "cardForm.get('name')"></app-inputvalidator>
</form>
Parent ts file
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormControl,Validators } from '#angular/forms';
#Component({
selector: 'app-card-form',
templateUrl: './card-form.component.html',
styleUrls: ['./card-form.component.css']
})
export class CardFormComponent implements OnInit {
nameFormControl ;
cardForm = new FormGroup({
name: new FormControl('', [Validators.minLength(5),Validators.maxLength(25)])
});
constructor() {
}
ngOnInit(): void {
this.nameFormControl = this.cardForm.get('name');
}
}
I am passing the nameFormControls to the child component and accessing it in the template as well as class as follows:
InputValidator.ts
import { Component, OnInit, Input } from '#angular/core';
import { FormControl} from '#angular/forms';
#Component({
selector: 'app-inputvalidator',
templateUrl: './inputvalidator.component.html',
styleUrls: ['./inputvalidator.component.css']
})
export class InputvalidatorComponent implements OnInit {
#Input() controls: FormControl;
constructor() {
}
ngOnInit(): void {
}
}
Input Validator.html
<input [formControlName] = "controls"
<br>
<div>{{ controls.errors | json}}</div>
The project is compiled successfully with no errors.
I am getting the value of controls.errors to always null.
Why can I not print the object controls.errors using string interpolation as the value in the name input box changes?
you get null becuase you don't put required validator the min,maxLength validators will return an error if there is value and the value is not valid , if the value is null or empty string this will consider a valid
check the validator 👉 source

Angular and Typescript Sending Post Request

I have a simple page with angular and typescript with just 1 button and 1 text field. I want to make a post request to a link that posts the string written in text box.
my button html:
<a class="button-size">
Add Customer
</a>
and button ts file:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'customer-button123',
templateUrl: './blabla',
styleUrls: ['./clacla']
})
export class AddCustomerButtonComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
text box html:
<mat-form-field>
<input matInput placeholder="Customer Name">
</mat-form-field>
text box ts file:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'customer-text-field',
templateUrl: './blabla2',
styleUrls: ['./clacla2']
})
export class CustomerTextFieldComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
and simple wrapper page html is:
<div class="input-label">
<mg-customer-text-field></mg-customer-text-field>
</div>
<div>
<mg-customer-button123></mg-customer-button123>
</div>
How can i send a post reques to link localhost8080/admin/addCustomer ?
If you hosting your front end at port: 4200 (default Angular port serve) and you want to send a request to http://localhost8080/admin/addCustomer, you will need a proxy configuration. You can see right here for more info: https://itnext.io/angular-cli-proxy-configuration-4311acec9d6f
You use the HttpModule
I use a service to separate http requests.
Example
import { Component, OnInit } from '#angular/core';
import { ApiService } from '../../services/api.service';
#Component({
selector: 'customer-button123',
templateUrl: './blabla',
styleUrls: ['./clacla']
})
export class AddCustomerButtonComponent implements OnInit {
data: any;
results: any;
constructor(private apiService: ApiService) { }
ngOnInit() {
}
getDataFromApi() {
this.apiService.getData(this.data).subscribe(results => {
this.results = results;
});
}
ApiService
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class ApiService {
apiUrl: string = environment.apiUrl;
constructor(private http: HttpClient) {}
getData(data): any {
return this.http.get(`http://localhost:8080/api/get-data`);
}
html
<div class="input-label">
<mg-customer-text-field [(ngModel)]="data"></mg-customer-text-field>
</div>
<div>
<mg-customer-button123 (click)="getDataFromApi()"></mg-customer-button123>
</div>

Display data from json array using angular4

I am new to angular so please help me. I have an api returning an array of objects containing name, place id.
I need to display this in different cards on my html page, the cards being a widget.
in the parent component under the ngOnInit() section how do I access this json data and loop through the array in order to display it on my page as different cards?
Thank you in advance.
import { Component, OnInit } from '#angular/core';
import {HttpClient} from '#angular/common/http';
import { Observable } from 'rxjs/observable';
#Component({
selector: 'app-home-page',
templateUrl: './home-page.component.html',
styleUrls: ['./home-page.component.css']
})
export class HomePageComponent implements OnInit {
showSplash = true
//public events: any = [];
events = [];
constructor(private http : HttpClient) { }
ngOnInit() {
this.showSplash = true
this.http.get("/events").subscribe(data => {
console.log("EVENTS ARE: ", data);
this.events = data;
console.log(this.events)
})
}
ngAfterViewInit(){
setTimeout(() => {
this.showSplash = false
}, 3000);
}
}
This will get you the events you want.
import { Component, OnInit, OnDestroy } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Subscription } from 'rxjs';
#Component({
selector: 'app-home-page',
templateUrl: './home-page.component.html',
styleUrls: ['./home-page.component.css']
})
export class HomePageComponent implements OnInit, OnDestroy {
showSplash = true
events = [];
subscription: Subscription;
constructor(private http: HttpClient) {}
ngOnInit() {
this.subscription = this.http.get("/events").subscribe(data => {
this.events = data;
this.showSplash = false;
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
You will have to implement a Child Component(EventComponent probably with the selector app-event) that will accept an event object as an #Input property. Then in your HomePageComponent Template, you can loop through the events like this:
<div *ngFor="let event of events">
<app-event [event]="event"></app-event>
</div>
Alternatively:
You can use the async pipe in your HomePageComponent's Template to avoid manually unsubscribing from the Observable Subscription. Your HomePageComponent Class code will change to:
import { Component, OnInit } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'app-home-page',
templateUrl: './home-page.component.html',
styleUrls: ['./home-page.component.css']
})
export class HomePageComponent implements OnInit {
events$;
constructor(private http: HttpClient) {}
ngOnInit() {
this.events$ = this.http.get("/events");
}
}
And then in HomePageComponent's Template:
<div *ngFor="let event of events$ | async">
<app-event [event]="event"></app-event>
</div>
Here's how your EventComponent would look like in this case:
import { Component, Input, OnChanges } from '#angular/core';
#Component({
selector: 'app-event',
templateUrl: './event.component.html',
styleUrls: ['./event.component.css']
})
export class EventComponent implements OnChanges{
#Input() event;
ngOnChanges() {
this.events$ = this.http.get("/events");
}
}