How to render a same Angular component with different data? I have an Angular component which renders based on the part of the url - javascript

I have a component that renders data based on the URL - '/lp/:pageId', :pageId is responsible for fetching data from the server called from ngOnInit().
ngOnInit(){
this.apiHelper.getData(this.route.snapshot.params.pageId);
}
I am facing an issue when ->
I open /lp/apple => this fetches data related to apple and renders properly
But when I'm on /lp/apple and press the link which navigates to /lp/banana => only the route changes but does not fetch any data as the component is already loaded.
I tried calling the function to fetch data whenever the route changes, but that breaks some existing functionalities.
Any help regarding good Angular practice with this issue would be helpful. Thank you.

You can define your data reactively. Instead of fetching inside ngOnInit, you can define a data observable that is dependent on the route param (since angular provides the route params as an observable on the active route):
public data$ = this.route.paramMap.pipe(
map(params => params.get('pageId')),
switchMap(pageId => this.apiHelper.getData(pageId))
);
constructor(private route: ActivatedRoute) { }
Here the data$ observable will emit the result of apiHelper.getData() whenever the route param changes.

Related

Populating Data in a view after an http call

I have a component that needs to display data that is fetched via an asynchronous http call to another server.
I have a service that fetches the data. It gets instantiated immediately, but the http call takes a few seconds to return. When it does, the page is already drawn and found errors for missing data.
In the ngOnInit() method of the component, I am attempting to fetch the data that is obviously not there yet.
What is the best/proper approach to fill in the data? is it to add a listener to the http response and then populate the component or is there another standard approach?
Thanks
I know I can add listeners in the component to subscribe to change events, but I'm wondering what the more correct approach is here.
The proper approach for this would be to use the async pipe.
Your .ts component:
export class MyComponent implements OnInit {
constructor(private service:Service){}
apiData$:any;
ngOnInit() {
apiData$ = thhis.service.getData();
}
}
And then in your .html component, you use the async pipe.
<div>{{apiData$|async}}</div>
You need to refresh the component when you receive the data.
I do that usually in the end of the call method.

Using window.history.state Causing Error On Page Reload In Angular 8

I'm using the following code to pass data to a route:
this.router.navigateByUrl('/myurl/goes/here', { state: { data: someData });
Now in the component i navigate to, i use the following code to get the data i passed from the first component.
this.incomingData = window.history.state.data;
Now the issue arrises when I reload the second component (Component B), i get an error telling my the data I passed to it is now undefined. (this.incomingData becomes undefined).
Is what am doing the correct way to pass and receive data between components or am I doing something wrong ?
Use angular ActivatedRoute service in component, that you navigate to
constructor(activeRoute: ActivatedRoute) {
// this.activeRoute.snapshot.data
console.log('Route Data', this.activeRoute.snapshot.data)
}

How do i update the rendered data of a react component?

I am making simple blog application, and i have a page for every individual post that is accessed this way:
http://localhost:3015/Post/post_id
And in the router i have set up the post component to render in this way:
<Route component={Post} path="/Post/post_id"></Route>
Then, in my post component i run the following code to make a call to the REST api im using:
componentDidMount(){
let id = this.props.match.params.post_id
axios.get('https://jsonplaceholder.typicode.com/posts/' + id)
.then(res => {this.setState({ //res is short for responce
post: res.data
})
})
this.setState({
id: id
})
}
And this works for the first post - when i click on a post it takes me to that individual post but after that, even though the URL changes, it doesnt update the component. I checked the state through the developer tools on chrome and realized that it doesn't update the state either.
Im new to react, and decided to take on this small project before using it full time, so excuse me if i made a rookie mistake. After all i am a rookie.
Component will re-render only if some of his props or state changes, and if it's already mounted, componentDidMount it's not called again. So, you can try to call the rest api through your componentDidUpdate method (when the match params changes).
componentDidUpdate() {
if (this.props.match.params.post_id != this.state.id) {
// make the http call and update id, and post state
}
}
https://reactjs.org/docs/react-component.html#componentdidmount

Pass data from dynamicallyloadedcomponent back to parent page Angular2

I'm wondering if there is any way to pass data back from a dynamically loaded component in Angular2. I pass the component data using
this._dcl.loadIntoLocation(...).then(component => {
component.instance.variable = this.variable;
}
On completing the tasks inside the component, in my case a modal, can I pass data or variables back out in a similar manner? Thanks in advance.
You can add an Observable to the dynamically added component
(an EventEmitter might work as well but might break eventually. Then Angular2 team doesn't guarantee that an EventEmitter will keep behaving like an observable)
Then just subscribe to this observable
this._dcl.loadIntoLocation(...).then(component => {
component.instance.variable = this.variable;
component.instance.someObservable.subscribe(val => this.someVal = val);
}
DynamicComponentLoader is deprecated and AFAIK was already removed in master.
See also Angular 2 dynamic tabs with user-click chosen components

Angular 2 transfer ajax call response to another component

I just started playing with angular 2 and i've ran into a small problem, that i ve searched for in various forms and also angulars documentation.
I've managed to make a service that makes a call and then i want in a component when i press a button to load another component with dynamicload component and have access to the ajax result.
The problem is that I can t figure out how to do that..
The question is how can I make the result accesible in other components using Observables or Promises method.
If I understood correctly your question, you are looking a way to insert a data from request to another nested component.
I hope this image will clarify for you the data flow for this case.
Your Root component is calling a service method which returns for you promise object.
Then you map needed data from response to the component model inside Root Component constructor.
And your Child component should be subscribed for the model which you was preparing in previous step.
ngOnInit() {
this.dataService.getSomeData()
.subscribe((data: IData) => {
this.data = data;
});
}
Just a short example above how to set model in the root component from the promise object to the local model.
New research:
There is another way to fill your components by data from api's. You can use EventEmitter to emit event from service, and then, you can subscribe for this event inside you created components, so they will get a data, each time there will be called the service. Here is nice example of this strategy in the first answer. Service Events
Hope it will help you, let me know if you will need additional info!
Just create a service, then inject the service where you want.
Here it's an example how to share a service ajax data across many components without making the request twice :
https://stackoverflow.com/a/36413003/2681823
the Service:
#Injectable()
export class DataService {
constructor(private http: Http) { }
private _dataObs = new ReplaySubject<request>(1);
getData(forceRefresh?: boolean) {
// On Error the Subject will be Stoped and Unsubscribed, if so, create another one
this._dataObs = this._dataObs.isUnsubscribed ? new ReplaySubject(1) : this._dataObs;
// If the Subject was NOT subscribed before OR if forceRefresh is requested
if (!this._dataObs.observers.length || forceRefresh) {
this.http.get('http://jsonplaceholder.typicode.com/posts/2')
.subscribe(
requestData => {
this._dataObs.next(requestData);
},
error => this._dataObs.error(error));
}
return this._dataObs;
}
}
the Component:
#Component({
selector: 'child',
template : `<button (click)="makeRequest()" class="btn">Click me!</button>`
})
export class Child {
constructor(private _dataService: DataService) { }
makeRequest() {
this._dataService.getData().subscribe(
requestData => {
console.log('ChildComponent', requestData);
}
}
}
A full working example/plunker can be found here : http://plnkr.co/edit/TR7cAqNATuygDAfj4wno?p=preview

Categories

Resources