how to send value to another unrelated component in angular 11? - javascript

in home component, a line like ...<app-root [message]="hii"> is opening that app-root comp , with value to app-root component which has #input and {{message}} in html is working..
But i need to redirect to that app-root component instead of opening in current component.
any ways like "button onclick to redirect to that with [message]="hi" as data?

the best way to shared data between an unrelated component in the angular is, use the "BehaviorSubject" from rxjs library.
we imagine that we have two components that there are completely unrelated and we want to shared data between them.
first of all, you should create a service file.
Imagine that we have a service with the name of sharing-data.serice.ts :
import { BehaviorSubject, Subject } from 'rxjs';
import { Injectable } from '#angular/core';
#Injectable({
providedIn:'root'
})
export class SharingDataService {
public subject = new BehaviorSubject("");
getDataFromFirstComponent(x){
this.subject.next(x);
}
sharedDataWithSecondComponent(){
return this.subject.asObservable();
}
}
here we use BehaviorSubject class to make a pipe between unrelated components for transferring data.
in the first component.ts we inject the service by dependency injection, then make a method to use this service and fill the pipe by data :
constructor(
private service : SharingDataService,
) { }
sendDataOutOftheComponent(){
this.service.getDataFromFirstComponent(this.dataFormFirst);
}
now in the second component we just need to use this service again and after that subscribe to the method to get the data.
in the second component.ts we have the following code :
constructor(
private service : SharingDataService,
) { }
getDataFromFirstComponent(){
this.service.sharedDataWithSecondComponent()
.subscribe(data=>{
this.dataFromFirst= data;
})
}
with this method, you can easily shared data between unrelated components in the angular

Related

How can I make a function run only when I reload the page with angular?

What I want to do is shuffle or riffle a number and then stock it in an array, to later use it in the view, but I only want this when I reload the page. The problem is that every time I go to the component it generate a new number. This number I am using to shuffle the order of my products in the view, order:
{{number}}.
IN THE COMPONENT:
public accesoriosJson:any
private current_value:any
constructor(private accesoriosService: AccesoriosService){
this.accesoriosService.getAccesorios().subscribe(respuesta =>{
this.accesoriosJson = respuesta;
this.accesoriosJson.map(currentValue =>{
this.current_value = currentValue;
this.current_value.random = Math.ceil(Math.random()*10);
})
})
}
IN THE VIEW:
<div class="div" *ngFor='let accesorios of accesoriosJson' style="order:{{accesorios.random}};" routerLink="{{accesorios.name}}">
<div class="lupa"><i class="fas fa-search"></i></div>
<img src="{{accesorios.logo}}">
</div>
</section>
I tried to do something with window.onload, but clearly I do not know how to use angular, and also I do not have so much experience with typescript, if somebody could help me I would really appreciate it! Thank you!
It's a new number, because each time the page is revisited, the component is re-created (a new instance of the component is created).
What you need is a singleton service. Singleton services are the ones that only have a single instance across the application.
So you can:
Create the service
Move your code to the service
Inject the service into your component.
That way, your number will instantiate only once, when the application loads, and each time you revisit the page, you will see the same number.
Documentation on singleton services.
Documentation on how to inject a service.
This is a very broad description, but as you can see from the information in the links provided, the full answer won't fit here.
A simple way is to subscribe to the router events and that will get you the page refreshed or not. NavigationStart is used to tell if the page loaded the first time.
import { Component, OnDestroy } from '#angular/core';
import { NavigationStart, Router } from '#angular/router';
import { Subscription } from 'rxjs';
export let browserRefresh = false;
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnDestroy {
name = 'Angular 6';
subscription: Subscription;
constructor(private router: Router) {
this.subscription = router.events.subscribe((event) => {
if (event instanceof NavigationStart) {
browserRefresh = !router.navigated;
}
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
Working Example:
https://stackblitz.com/edit/angular-r6-detect-browser-refresh
A solution can be to generate your random number into the root component (propably app-component if you didn't changed it) in the ngOnInit() function. Please avoid put code in constructor() function.
After your number as been generated, you can pass it to all the components you want : by using #Input/#Output if you have a parent/child hierarchy, or by using a service if you want to share it to every component wherever you want

How to update view from another component in Angular 7?

I'd like to refresh my card set from navigation bar which is part of app.component.html so I prepared refresh() function.
When it is called it does update variable Cards but doesn't render it in ngFor on html element in mainView.html.
It does render updated set if I call from html element in mainView.html (as (click)="loadCards()") but not if the same ((click)="refresh()") is done in app.component.html.
export class MainView implements OnInit {
constructor(private mMainController: MainController) {}
Cards: any = [];
ngOnInit() {
this.loadCards();
}
loadCards() {
this.mMainController.getAllCards().subscribe(
(data) => {this.Cards = data); },
(error) => {},
() => {console.log(this.Cards));
}
...
}
export class AppComponent {
...
constructor(private router: Router, private mMainView: MainView) {}
refresh(){
console.log('done');
this.mMainView.loadCards();
}
...
}
Update
Tried with #Input() but couldn't get it work. I implemented RefreshService as explained in accepted answer and now I'm able to refresh content from other components.
Thank you all for quick response.
FIST WAY: USING A SHARED SERVICE
You need to introduce a service that manage the state of your car.
In this case it may be usefull to introduce for this a BehaviorSubject like this:
Your Service:
private refresh: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
public getRefresh(): Observable<boolean> {
return this.refresh.asObservable();
}
public setRefresh(value: boolean): void {
this.refresh.next(value);
}
Inside your MainView class
First: inject your service as dependency
Second: Subscribe to your observable inside OnInit hook e.g like this:
this.myService.getRefresh().subscribe((value: boolean) => {
if(value) {
this.loadCards()
}
})
Inside your AppComponent class
First: inject your service as dependency
Second: Set the value of your observable inside your refresh method.
e.g something like this:
public refresh(){
this.myService.setRefresh(true);
}
SECOND WAY: USING #Input Decorator to pass value down.
You're attempting to use MainView as a dependency but it's not an injectable dependency. Try to use inputs/outputs between app component and MainView, if possible. If MainView isn't a child of AppComponent then abstract the logic for loading cards into a service and inject it into both.
You can implement the component interaction in two ways
(i) If the components are related to each other use the common and straightforward method of sharing data. It works by using the #Input() decorator to allow data to be passed via the template.
(ii) If the components are not related to each other you can use a shared service using subject to communicate between the two components

Trigger functions in different components with a buttonclick via service in Angular?

I have a dashboard, where I can type in data in a component and the data is going in a mongoDB. Then I get that data in other components and display it at the same site. Now I just have an update button under each component, that I can manually update every component. But I want to do that in this moment, where I submit my data, that is going to mongodb.
I tried it with a service, but it didn't worked out very well
This should be updated
import { UpdateServicenter code heree} from "../../../#core/data/update.service";
constructor(private http: HttpClient, private updateService: UpdateService,) {
//load it the first time if you refreshing the site
this.updateOrders();
//this should call updateOrders again if button is clicked
this.updateService.updateData()
}
updateOrders() {
//here I get the data from mongoDB and set it in my variables
}
Button (This function is called, if I push the button)
import { UpdateService} from "../../../#core/data/update.service";
constructor(private http: HttpClient,private updateService: UpdateService){}
submitButton(){
this.updateService.updateData()
}
Service
#Injectable()
export class UpdateService {
updateData(){
//this should call the function updateOrders()
}
}
I want to create a service, that can call every function or can be called, if the button is pushed, because I have more than one component which should be updated.
the method updateOrders() is an http call where you receive an observable object?
Great. Move this method into the service, save your data into variables in the service and then pass the data as input to each component, like this the ngOnChanges lifecycle hook will fire each time your data gets updated. e.g.
#Injectable()
export class UpdateService {
public obj; //variable you save your data
updateOrders() {
this.someObj = this.http<>.....
}
getObj():{
// do your stuff here if you need so
return this.obj;
}
}
<someComp [obj]="updateService.getObj()"></someComp>
export class SomeComponent {
#Input()
public obj;
ngOnChanges(changes:SimpleChanges){
//do your stuff here if you need so, or hust send them to html
}
}

pass data to different component in angular 6

I am building my web application using angular 6. I have some common component which is common on all routes. For example I have a filter component which is common on all route. Now when user select a filter a click on find this filter data should be passed to different component on same route and then result should be display. PFB my angular's app structure :
App.component.html :
<filter (messageToDash)="receiveMessage($event)"></filter>
<router-outlet></router-outlet>
For dash route I have dash component. PFB is code for dash.component.html :
<dashboard></dashboard>
Filter.component.html
<button (click)="somemethod()"></button>
So when user click on button, I want to want to pass some variable to the dashboard component. I also tried using service component and subscribe it into dashboard's ngOnInit() variable, but its not working.
Create a service and give it as reference at the parent Level and on (click) of the the button pass the filter data to the function with return type observable and in component subscribe to the result of the function.
Since ngOnInit lifecycle is initialized only at the beginning of the page load, It may not be of much help.
I too had stuck in the same problem a few months back, the best solution i got at that time was using LocalStorageService
For Example:
import { LocalStorageService } from 'ngx-webstorage';
constructor(private session: LocalStorageService)
{
//works at the begining of the module before OnInit
}
some_function()
{
this.session.store('key_name',yourData);
}
Now in another component just import LocalStorageService and create a obj for it and then:
some_function()
{
this.your_variable = this.session.retrieve('key_name');
}
Note: the key_name for storing and retrieving must be same.
hope this helps.

Binding to Correct Service Call in My Angular 2 App

In my Angular 2 app I have several different components that display data for different groups. Each of the different groups has a different API service call. Other than the different data set, though, the tabular display/layout itself is the same for each one.
In the component for each respective group, I am using the service call like this (this one is for "group1"). I am subscribing to the data in my OnInit in my group1.component.ts:
ngOnInit() {
this.group1Service.getGroup()
.subscribe(resRecordsData => this.records = resRecordsData,
responseRecordsError => this.errorMsg = responseRecordsError);
}
Now, what I'd like to do is cut down on the duplication (i.e. make it dry-er) by abstracting out the tabular display so I can just drop that into each component view as a child view. So the view for component 1, for instance would look like this ("table-display" is the part that's abstracted out in the below code):
<div class="page-view">
<div class="page-view-left">
<comp1-left-panel></comp1-left-panel>
</div>
<div class="page-view-right">
<div class="page-content">
<table-display></table-display>
</div>
</div>
</div>
My question is, how can I bind the right service call (i.e. the right component) to the "table-display" for each component? Would I use an #Input here, or perhaps square bracket binding?
Yes, you would use an input on your table-display component and fill it from the parent component:
<table-display [Data]="arrayOfData"></table-display>
Where [Data] is define in your table-display as:
#input Data: Array<any>;
You can pass required data as Input to table-display component.
If all of the components shares same type of structure to show data in table. Then I would recommend to create a separate class for common data and pass the object of that common class.
You can write a mapper function in each component which will return the required data to table-display , alternatively if it's a simple JSON like structure then you can pass it on fly.
e.g
Let's say there are 4 attributes you need to show in table-display ,
We create common.ts
export class Common {
col1: string; #whatever data structure you need
col2: number;
col3: number[];
col4: Object;
constructure(col1: any,col2: any,col3: any,col4: any){
this.col1 = col1;
//set other attributes similarly
}
}
no in component1.component.ts
import {Common} from './path_to_common.ts'
#other imports here
#component {
selector: 'app-component1',
template: "your about template"
}
export class Component1Component implements OnInit{
common: Common; #this is the common attribute you will pass to **table-display**
constructure(component1_service: Component1Service){
}
ngOnInit(){
#get your data from service here
#now set **common** attribute here by settings 4 attributes we defined
#e.g
this.common = new Common(service_record.col1,service_record.col2....)
}
}
that's it now you can pass this common attribute as input by:
in your component templates
<table-display [common]="common"></table-display>
now write TableDisplayComponent
import {Input} from '#angular/core'
`import {Common} from './path_to_common.ts'
#other imports here
#component {
selector: 'table-display'
template: `what ever your template is to show table`
}
export class TableDisplayComponent{
#Input() common: Common; #This common will be passed as input from all of your components
}

Categories