Call an event in Angular Element from custom Element using ID Angular - javascript

I have been stuck at one place where I am trying to call the Custom element event into the angular element using id
for example:
angularElement.html
<custome-element id="elementId"></custome-element>
AngularElement.Ts
import {
Component,
} from '#angular/core';
#Component({
selector: 'angular-element',
templateUrl: './angular-element.component.html',
styleUrls: ['./angular-elementcomponent.scss'],
})
export class AngularElementComponent implements OnInit {
callThisFunction() {
const data: any = document.getElementById('elementId') as
HTMLElement
data.someFunction(); // not working
console.log('call function in to custom element');
alert('test');
}
}
CustomeElement.Ts
import {
Component,
Input,
OnInit,
EventEmitter
} from '#angular/core';
#Component({
selector: 'custome-element',
templateUrl: './custome-element.component.html',
styleUrls: ['./custome-elementcomponent.scss'],
})
export class CustomeElementComponent implements OnInit {
constructor() {}
ngOnInit(): void {
}
someFunction() {
console.log('call function in to angular element');
alert('test');
}
}
Here I want to call the function someFunction() in the Angular element using ID, I know I can call with #output but I need to use ID and call function using the ID.
Here is what i am trying by passing id
const data: any = document.getElementById('elementId') as HTMLElement
data.someFunction(); // not working

You need to declare an output in child component
#Output() callParentFunctionName = new EventEmitter<void>();
and then emit it
someFunction() {
this.callParentFunctionName.emit();
alert('test');
}
And then in parent component
<custome-element [passdata]="true" (receiveData)="addData()" (callParentFunctionName)="callThisFunctionOnCustomElement()"></custome-element>
Or if You want to call child component function in parent component
https://angular.io/guide/component-interaction#parent-calls-an-viewchild
Or by using dispatch event
callTheCardBtn() {
const data: any = document.getElementById('recaptchaId');
const event = new CustomEvent("addCard", { detail: { name: "Custom Event Triggered" } });
data.dispatchEvent(event);
alert('click me');
}

Related

Multilevel data passing in Angular

Suppose you have a parent component A and inside of it you have some variable x. You would like to pass this variable to the child component B. Easy! Just use #Input annotation and call it a day. But what if B has another child component C? How would we pass x from A to C? I tried using the same approach to pass it from B to C, but it only passes the value undefined.
You can use a common service file which is data.service.ts file in this case. This service will be injected by both the parent and grand child. When component A which is grand parent here want to send a data it will call the deliverMsg method of the data service file. The component C which is grand child will listen to this change by injecting the same data.service
data.service.ts
// relevant imports
#Injectable()
export class DataService {
private message = new BehaviorSubject('default message');
portMessage = this.message.asObservable();
constructor() { }
deliverMsg(message: string) {
this.message.next(message)
}
}
parent.component.ts
//all relevant imports
#Component({
selector: 'app-parent-a',
template: 'html file url',
styleUrls: ['./sibling.component.css']
})
export class ParentComponent implements OnInit {
message:string;
constructor(private data: DataService) { }
ngOnInit() {
}
newMessage() {
this.data.deliverMsg("Hello from Grand Parent")
}
}
grandchild.component.ts
// all relevant imports
#Component({
selector: 'app-sibling',
template: 'template',
styleUrls: ['./sibling.component.css']
})
export class SiblingComponent implements OnInit {
message:string;
constructor(private data: DataService) { }
ngOnInit() {
this.data.portMessage.subscribe(message => this.message = message)
}
}
Alternatively you can also you NgRx

Angular 10: Console shows my object as "unidentified" (pass data from parent to child)

I am trying to pass data from the parent to the child. I get the correct output when I pass the string (data1) from parent to child but when I try to display object (data) the console says it's unidentified and nothing is displayed on the screen.
Parent Component:
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
data={
name:'Charles',
age:24,
email:'charles#gmail.com'
};
data1 = "Charles";
}
<app-contact [sendName] ="data"></app-contact>
Child Component
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'app-contact',
templateUrl: './contact.component.html',
styleUrls: ['./contact.component.css']
})
export class ContactComponent implements OnInit {
#Input() sendName;
constructor() { }
ngOnInit(): void {
console.log(this.sendName);
}
}
<h1 class="text-center">Contact Form</h1>
<h3 class="pb-5">from the parent {{sendName.name}}</h3>
<h3 class="pb-5">from the parent {{sendName.age}}</h3>
please someone help me.
Thank you
If your data (in parent component) variable has static value then your child component will be
#Input() sendName;
ngOnInit(): void {
console.log(this.sendName);
}
If your data (in parent component) variable will assign from dynamic value then your child component will be
(Assume you have an API to call and update sendName variable on API response, but our child component is initialised without waiting the API response then we need to trigger #Input() to send updated data in child component )
#Input() set sendName(value: any) {
if(value){
console.log(value);
this.name = value
// call any function from here
}
}
name:any; // use this variable at anywhere
constructor(){
}
you might be rendering the child, before setting the value in data in parent
in Child component import Onchanges and get from ngOnchanges()
import { Component, OnInit, Input ,Onchanges} from '#angular/core';
export class ContactComponent implements OnInit,Onchanges {
#Input() sendName; constructor() { }
ngOnChanges() {
console.log(this.sendName); }

How do I pass data from one component to another (New Browser Tab) in angular?

I'm new to angular and I don't know how to pass data between two components using routers. This is my first component view,
when I press view report button I need to call another component with the first component data. This is my first component view report click button code.
<button type="button" (click)="onFuelViewReport()" class="btn btn-success ">
<b>view Report</b>
</button>
when clicking the button it calls onFuelViewReport() function in the first component and using this function it opens the second component view with a new browser window (tab). What I want is to pass data from the first component to the second component from here. Please help me to do this.
onFuelViewReport() {
this.router.navigate([]).then(result => {
window.open("/pages/view-report", "_blank");
});
}
If you want to share data from child component to parent component, you can use #Output event emitter or if your are trying to share data within unrelated components, you can use BehaviourSubject (This also works in case of parent to child component communication and vice versa).
Child to Parent: Sharing Data via Output() and EventEmitter
parent.component.ts
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
}
}
child.component.ts
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 = "Hola Mundo!"
#Output() messageEvent = new EventEmitter<string>();
constructor() { }
sendMessage() {
this.messageEvent.emit(this.message)
}
}
Unrelated Components: Sharing Data with a Service
data.service.ts
import { Injectable } from '#angular/core';
import { BehaviorSubject } from 'rxjs';
#Injectable()
export class DataService {
private messageSource = new BehaviorSubject('default message');
currentMessage = this.messageSource.asObservable();
constructor() { }
changeMessage(message: string) {
this.messageSource.next(message)
}
}
parent.component.ts
import { Component, OnInit } from '#angular/core';
import { DataService } from "../data.service";
#Component({
selector: 'app-parent',
template: `
{{message}}
`,
styleUrls: ['./sibling.component.css']
})
export class ParentComponent implements OnInit {
message:string;
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentMessage.subscribe(message => this.message = message)
}
}
sibling.component.ts
import { Component, OnInit } from '#angular/core';
import { DataService } from "../data.service";
#Component({
selector: 'app-sibling',
template: `
{{message}}
<button (click)="newMessage()">New Message</button>
`,
styleUrls: ['./sibling.component.css']
})
export class SiblingComponent implements OnInit {
message:string;
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentMessage.subscribe(message => this.message = message)
}
newMessage() {
this.data.changeMessage("Hello from Sibling")
}
}
The window.open looks absolutely awful. Use this.router.navigate(['/heroes']);.
So if I understand correctly you have a list of items and when you click on one of the items, the details page of that item should open?
Best practice is to allow the detail route to have a property to set. the Angular Routing & Navigation page is very complete. It shows that you should use :id - { path: 'hero/:id', component: HeroDetailComponent }. When you open the detail page, you get the id variable and then get the data for it.

Angular: Blur and empty a form field on click without jQuery?

I have a form input which I would like to blur (de-focus) and empty when a button is clicked.
In AngularJS, I did this in the controller like so:
angular.element('#search-input').val('');
angular.element('#search-input').blur();
In Angular (4.4.4) I have it working like so:
$('#search-input').val('');
$('#search-input').blur();
But I'd rather not use jQuery. What's the proper way to do this in Angular?
Here's the whole component:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'pb-header',
templateUrl: './header.component.html'
})
export class HeaderComponent implements OnInit {
private searchActive: boolean;
constructor() {
this.searchActive = false;
}
ngOnInit() {
}
toggleSearch = function () {
if (this.searchActive) {
this.searchActive = false;
$('#search-input').val('');
$('#search-input').blur();
} else {
this.searchActive = true;
}
};
}
You can use NgForms reset method:
#ViewChild(NgForm)
public form:NgForm;
form.reset(<value>);
Also there is no need for blur, since you are clicking button and it will take focus, if it does not, set tabindex attribute of the button.

Interdependent component which need to communicate each other

I am in a situation like i have 5 interdependent component which need to communicate each other. For example if i click on a button A on all other 4 component need to listen to the click and alert something. The same way button in other component also listened by all other 4. Need a best solution on how to achieve this.
here is my code snippet
import { Component, OnInit } from '#angular/core';
import { CommonService } from 'broadcast-recive/service/common-service';
#Component({
selector: 'app-broadcaster',
templateUrl: './broadcaster.component.html',
styleUrls: ['./broadcaster.component.css']
})
export class BroadcasterComponent implements OnInit {
constructor(private commonservice: CommonService) { }
ngOnInit() {
}
broadCastMe(): void
{
this.commonservice.btnClickedInBroadCasterComponent((<HTMLButtonElement>event.target).id);
}
}
import { Component, OnInit } from '#angular/core';
import { CommonService } from 'broadcast-recive/service/common-service';
#Component({
selector: 'app-listener1',
templateUrl: './listener1.component.html',
styleUrls: ['./listener1.component.css']
})
export class Listener1Component implements OnInit {
constructor(private commonservice: CommonService) { }
ngOnInit() {
this.commonservice.clickStatusForBroadCastercomponentBtn.subscribe((id: string) => {
alert('alert from listner 1');
})
}
}
import { Component, OnInit } from '#angular/core';
import { CommonService } from 'broadcast-recive/service/common-service';
#Component({
selector: 'app-listener2',
templateUrl: './listener2.component.html',
styleUrls: ['./listener2.component.css']
})
export class Listener2Component implements OnInit {
constructor(private commonservice: CommonService) { }
ngOnInit() {
this.commonservice.clickStatusForBroadCastercomponentBtn.subscribe((id: string) => {
alert('from listner 2');
});
}
}
Here am always getting alert box "from listener 2 " , My requirement is its should trigger both the listener. Please help me refactoring the code. blow is my service where am using rx js for subscribing.
import {Subject} from 'rxjs/Subject';
import { Injectable } from '#angular/core';
#Injectable()
export class CommonService {
public clickStatusForBroadCastercomponentBtn = new Subject<string>();
public clickStatusForBcomponentBtn = new Subject<string>();
btnClickedInBroadCasterComponent(btnId: string): void {
this.clickStatusForBroadCastercomponentBtn.next(btnId);
}
btnClickedInComponentB(btnId: string): void {
this.clickStatusForBcomponentBtn.next(btnId);
}
}
You can do this using rxjs Subject declared in a service. Lets say, you have a service named AService:
import {BehaviorSubject} from 'rxjs/BehaviorSubject;
#Injectable()
export class AService {
public clickStatusForAcomponentBtn = new BehaviorSubject<string>('');
public clickStatusForBcomponentBtn = new BehaviorSubject<string>('');
btnClickedInComponentA(btnId: string): void {
this.clickStatusForAcomponentBtn.next(btnId);
}
btnClickedInComponentB(btnId: string): void {
this.clickStatusForAcomponentBtn.next(btnId);
}
}
Now, you can use this service in all your components those need to communicate with each other like this:
export class AComponent implement OnInit {
constructor(private aService: AService){}
ngOnInit(){
this.aService.clickStatusForBcomponentBtn .subscribe((clickedBtnId:string)=> {
// whenever button with id clickedBtnId clicked in Component B this observer
// will be get executed.So, do your necessary operation here.
}
}
btnClickListenerForA(event:Event){ /* in this component template you'll bind this listener with your button click event */
this.aService.btnClickedInComponentA((<HTMLButtonElement>event.target).id);
}
}
export class BComponent implement OnInit {
constructor(private aService: AService){}
ngOnInit(){
this.aService.clickStatusForAcomponentBtn .subscribe((clickedBtnId:string)=> {
// whenever button with id clickedBtnId clicked in Component A this observer
// will be get executed.So, do your necessary operation here.
}
}
btnClickListenerForB(event:Event){ /* in this component template you'll bind this listener with your button click event */
this.aService.btnClickedInComponentB((<HTMLButtonElement>event.target).id);
}
}
If you review the code, you'll understand two subjects are used to pass communication between two component. This way, you'll able to communicate between any number of components.
Thus, you can declare a rxjs subject for every button and for listening any button's click event you've to subscribe that buttons subject in other components where you want to listen that buttons event.
Hope this will guide you in a right direction.
You should use a shared service with a BehaviorSubject to emit any changes to any component listing to it please take a look at my answer Here I posted it like a few seconds ago on a similar question.

Categories

Resources