How to share the http response between two components in angular 6? - html

I have a component named modal. In this model ts file, Im making a http request to get json data from node js. After retrieving Im just displaying it in a table format. My table structre is like below.
modalId modalName subModal AddSubmodal
111 modal1 add
112 modal2 add
The problem here is after clicking the add button, one pop up box will come(Another component) asking us to enter sub model name. There we should display the modal name for which we have to enter sub model details.
So After clicking the add button, I need to pass the modalId to fetch the model details. So here I need to pass the modalID dynamically to the addmodel(second) component. Can anybody tell me how to do this?
My modal.component.ts:
#Component({
selector: 'app-modal',
templateUrl: './modal.component.html',
styleUrls: ['./modal.component.css']
})
export class ModalComponent extends Lifecycle {
public d: any;
constructor(
private $modal: $ModalManagerService,
private http: HttpClient,
) {
super();
}
_initialize(): void {
this.http.get('/getModel',{responseType:"json"}).subscribe(
response => {
this.data = response;
var sample=JSON.stringify(response);
});
}
addSubmodal(modalId){
let obj = this.$modal.show(AddSubModalComponent)
.subscribe(r => {
obj.unsubscribe();
});
};
My modal html:
<table class="table table-bordered" >
<thead>
<tr>
<th>modal ID</th>
<th>modal Name</th>
<th>SubModal</th>
<th>AddSubmodal</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let i of d">
<td>{{ i.Record.modalId }}</td>
<td>{{ i.Record.modalName }}</td>
<td></td>
<td>
<img src="./../Add_Icon.svg" (click)="addSubmodal(i.Record.modalId);">
</td>
</tr>
</tbody>
</table>
As I'm new to angular, Im just browsing angular answers in stackoverflow & doing it. Please tell me how to achieve this in my second component html file?

Use Input & Output Decorators
Basic concept ---> DEMO
app.component.html:
<app-component1 (elm)="catch1Data($event)">
</app-component1>
<app-component2 [elm]="datatocomp2" *ngIf="datatocomp2"></app-component2>
parent component : {{datatocomp2 | json}}
app.component.ts:
datatocomp2: any;
catch1Data(data) {
console.log(data)
this.datatocomp2 = data;
}
component1.ts:
#Output () elm : EventEmitter<any> = new EventEmitter<any>();
objectData: any;
constructor() { }
ngOnInit() {
let objectData = {
comp: 'component 1',
data: 'anything'
}
this.objectData = objectData;
this.elm.emit(objectData)
}
component2.ts:
#Input() elm: any;
constructor() { }
ngOnInit() {
console.log(this.elm);
}

Use a shared service to share data between components, event emitter method isn't the best way for components in routing
Simple example , create a datashare service
//DataShare Service
import { ReplaySubject } from 'rxjs/Rx';
export class DatashareService {
private dataObs$ = new ReplaySubject<any>(1);
getData() {
return this.dataObs$.asObservable();
}
updateData(data) {
this.dataObs$.next(data);
}
constructor() { }
}
In the component where you fetch data,
import { DatashareService } from '../datashare.service';
update the value of the observable
this.dataService.updateData(this.modal_id);
Subscribe to the observable from the sub components
import { Component, OnInit,OnDestroy,NgZone } from '#angular/core';
import { DatashareService } from '../datashare.service';
import { Subscription } from 'rxjs/Subscription';
In the constructor,
constructor(private dataService: DatashareService
,private zone:NgZone){}
Now, access data on init,
ngOnInit() {
this.subscription.add(this.dataService.getData().subscribe(data => {
this.zone.run(()=>{
console.log(data);
this.modal_selected=data;
})
}))
}
Don't forget to unsubscribe on destroy
ngOnDestroy() {
// unsubscribe to ensure no memory leaks
this.subscription.unsubscribe();
}

Related

I'm trying to do a http get request to get data from my backend Larval, MYSQL I have created the API in Laravel but cant display the data in Angular

I'm new to programming and new advise please here is my code
employees component
import { DataService } from './../../service/data.service';
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-employees',
templateUrl: './employees.component.html',
styleUrls: ['./employees.component.css'
]})
export class EmployeesComponent implements OnInit {
employees: any
constructor(private dataservice: DataService) { }
ngOnInit() {
}
getEmployeesData() {
this.dataservice.getData().subscribe((res: any) => {
this.employees = res;
});
}
}
data.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class DataService {
getData: any;
constructor(private httpClient: HttpClient) {
this.httpClient.get('http://127.0.0.1:8000/api/employees')
};
}
HTML
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Surname</th>
<th scope="col">Email</th>
<th scope="col">Salary</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let emp of employees">
<th scope="row">{{emp.id}}</th>
<td>{{emp.name}}</td>
<td>{{emp.surname}}</td>
<td>{{emp.email}}</td>
<td>{{emp.salary}}</td>
</tr>
</tbody>
I see a couple of things, that cause the Data not to show up.
data.service.ts:
Your fetching the Data in the Constructor but you do ignore the return Value of your call. I suggest you do the call in a separate function that will be called if the data is needed.
constructor(private httpClient: HttpClient) {}
loadAllEmployees(): Observable<any> {
return this.httpClient.get('http://127.0.0.1:8000/api/employees');
}
Employees Component:
It seems, that you do not call the getEmployeesData function. Therefore your employees never get any Data.
employees: any
constructor(private dataservice: DataService) { }
ngOnInit() {
this.getEmployeesData();
}
getEmployeesData() {
this.dataservice.loadAllEmployees().subscribe((res: any) => {
this.employees = res;
});
}
With this setup, your data should load and be displayed.
Besides that, I would suggest you define the Type of the Employee and do not work with any. It does make it easier to read and understand your code. You are also less likely to get any Errors regarding types.

Data NOT refreshing onSubmit Form and route change, Angular 6

I can't figure out why the data does NOT update in my table, when I make a change (post, delete, etc.) to the SQL database. I have to refresh the browser every time to see the update in the table.
This is a simple list that gets updated when submitting a form with changes. At the end of the onSubmit function, it routes back to fleet-home, but the table shows the old data (until browser refresh). No errors.
I feel like I'm missing a major Angular step here (still new to Angular).
I've tried adding "...this.ngZone.run(...).." to the router navigate, but it's not refreshing the data.
I read that "...this.route.paramMap.subscribe(...)" can listen for data changes, but it's not working (perhaps I'm not using it correctly).
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute, Params, Router } from '#angular/router';
import { FleetService } from 'src/app/fleet.service';
import { NgForm } from '#angular/forms';
#Component({
selector: 'app-fleet-home',
templateUrl: './fleet-home.component.html',
styleUrls: ['./fleet-home.component.css']
})
export class FleetHomeComponent implements OnInit {
public assignmentList: Array<any>;
public vehicleList: Array<any>;
id: number;
editMode = false;
constructor(
public route: ActivatedRoute,
public router: Router,
private fleetService: FleetService
) {
fleetService.getVehicleList().subscribe((importVehicleList: any) => this.vehicleList = importVehicleList);
fleetService.getAssignmentList().subscribe((importAssignmentList: any) => this.assignmentList = importAssignmentList);
}
ngOnInit() {
this.route.paramMap.subscribe(map => {
// adding this did not help, not sure if this is correct
this.fleetService.getAssignmentList().subscribe((importAssignmentList: any) => this.assignmentList = importAssignmentList);
});
}
}
Component with onSubmit...
onSubmit(form: NgForm) {
const value = form.value;
const assigmentAdd = form.value;
var newAssignmentObject = {
Id: assigmentAdd.Id,
CameraId: assigmentAdd.CameraId,
VehicleId: assigmentAdd.VehicleId,
DateCreated: assigmentAdd.DateCreated,
Deleted: assigmentAdd.Deleted
}
this.fleetService.addAssignment(newAssignmentObject).subscribe
(data => {
this.ngZone.run(() => this.router.navigate(['/fleet-home'])).then();
});
}
fleet-home HTML table...
<table class="table table-hover" id="searchTable">
<thead>
<tr>
<th>Date Created</th>
<th>Vehicle Assigned to</th>
<th>Camera</th>
<th>Edit and/or Delete Assignment</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let mat of assignmentList; let in = index" style='text-align:left;'>
<td *ngIf="mat.deleted === false">{{ mat.dateCreated | date: 'medium' }} </td>
<span *ngFor="let veh of vehicleList">
<td *ngIf="mat.vehicleId === veh.id && mat.deleted === false"> {{ veh.name }} </td>
</span>
<td *ngIf="mat.deleted === false">{{ mat.cameraId }} </td>
<td *ngIf="mat.deleted === false"> <a [routerLink]="['/fleet-home/fleet-edit/', mat.id]">EDIT or
DELETE</a> </td>
</tr>
</tbody>
</table>
You have to just call the function that fetch the records.
This is Not Possible in angular2, reason is once you load any component that component is only reload once you navigate from another route to that route again.
But you can reload forcefully
Basically there are two methods which are
you can call ngOnInit() method again and again as per need, which is not a recommended way
you can call one commonn method from ngOnInit() and later as per need call that function again like this
ngOnInit(){
this.callingFunction();
}
forLaterUse(){
this.callingFunction();
}

Difficulty fetching json data from API using Angular

I am trying to fetch data from API https://sportsbook.draftkings.com/api/odds/v1/leagues/3/offers/gamelines.json
and store them in table in my Angular Application. Initial 15 rows are displayed on my page, not all the rows. And I cannot fetch line data which is nested inside outcome object.
Here is my HTML code
<div class="row">
<mat-toolbar color="primary">
<span>Welcome!</span>
</mat-toolbar>
<div class="container">
<br>
<h2>Information</h2>
<span class="right">API endpoint</span>
<table class="table table-hover">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>HomeTeamName</th>
<th>AwayTeamName</th>
<th>Start Date</th>
<th>Offers</th>
<th>Line</th>
<!--<th>Image</th>-->
</tr>
</thead>
<tbody>
<ng-container *ngFor="let data of data.events">
<tr>
<td>{{data.id}}</td>
<td>{{data.name }}</td>
<td>{{data.homeTeamName }}</td>
<td>{{data.awayTeamName}}</td>
<td>{{data.startDate }}</td>
<td>{{data.offers[1].label }}</td>
<td>{{data.offers.outcomes[2].line }}
<!--<td><img class="image-width" src="{{contact.image}}" alt="{{contact.name}}}"></td>-->
</tr>
</ng-container>
</tbody>
</table>
</div>
</div>
Here is my typescript code
import { Component, OnInit } from '#angular/core';
import { Http, Response } from '#angular/http';
import 'rxjs/add/operator/map';
import { MatTableDataSource, MatSort } from '#angular/material';
import { DataSource } from '#angular/cdk/table';
#Component({
selector: 'app-draftking',
templateUrl: './draftking.component.html',
styleUrls: ['./draftking.component.css']
})
export class DraftkingComponent implements OnInit {
private apiUrl = 'https://sportsbook.draftkings.com/api/odds/v1/leagues/3/offers/gamelines.json';
displayedColumns = ['id','name', 'homeTeamName','awayTeamName','offers','line'];
data: any = {};
dataSource = this.data;
constructor(private http: Http) {
this.getLeague1();
this.getData1();
}
getData1(){
return this.http.get(this.apiUrl)
.map((res: Response) => res.json())
}
getLeague1() {
this.getData1().subscribe(data => {
console.log(data);
this.data = data
})
}
ngOnInit() {
}
}
Typically you setup your actual server call in a service (called model because it models your data). Here is one of mine as an example.
service.ts
#Injectable()
export class ApiService {
constructor(private http: HttpClient) { }
public get<T>(path: string, routerParams?: Params): Observable<T> {
let queryParams: Params = {};
if (routerParams) {
queryParams = this.setParameter(routerParams);
}
return this.http.get<T>(this.path(path), { params: queryParams });
}
public put<T>(path: string, body: Object = {}): Observable<any> {
return this.http.put(this.path(path), body);
}
public post<T>(path: string, body: Object = {}): Observable<any> {
return this.http.post(this.path(path), body);
}
public delete<T>(path: string): Observable<any> {
return this.http.delete(this.path(path));
}
...
In my components (sometimes other services) I will call an API method and expect results in the form of an Observable. So in your case I'd use my service like this:
component
constructor(private apiService: ApiService) { }
ngOnInit() {
this.apiService('https://pathtoserver').subscribe(data => {
if (data.id) {
this.setCurrentUser();
}
});
}
Hey remember to NOT call getData1(); more than once or you'll have 2 "hot" subscriptions. Use .pipe(take(1)).sub... in order to end subscriptions once they give you something.

Angular 6 Datatable refresh data in table after outside filtering

i'm trying to render the rows in the table after request.
i can see the the response in the browser and i am pushing the new data to the
ROWS: object,
but the table is not refreshing the rows in table.
sample code:
import {Component, OnDestroy, OnInit} from '#angular/core';
import { Subject } from 'rxjs';
import { XXXXXXXService } from './NAME.service';
#Component({
selector: 'app-NAME',
templateUrl: './NAME.component.html',
styleUrls: ['./NAME.component.scss']
})
export class XXXXXXXComponent implements OnDestroy, OnInit {
dtOptions: DataTables.Settings = {};
rows = [];
dtTrigger: Subject<any> = new Subject();
constructor(private XXXXXXXService: XXXXXXXService) { }
ngOnInit(): void {
this.rows.length = 0;
this.dtOptions = {
pagingType: 'full_numbers',
pageLength: 25
};
this.class.getRows()
.subscribe(rows => {
console.log(rows);
this.rows = rows;
// Calling the DT trigger to manually render the table -- not working!!!
this.dtTrigger.next();
});
}
render_rows_filters(filter) {
this.class.getRowsFiltered(filter).subscribe(
rows => {
this.rows = rows;
this.dtTrigger.next();
}
);
}
ngOnDestroy(): void {
this.dtTrigger.unsubscribe();
}
}
html
<table datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" class="table-bordered">
<!--class="row-border table-bordered hover">-->
<thead>
<tr>
<th> NAME</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of rows">
<td>{{ row.Name }}</td>
</tr>
</tbody>
</table>
Ok,
the thing is that when you use angular with components and services, one component can't declare the DataTable Element to another component running in the same page.
the solution was to create a outside (Global) service and pass all the component variables.
then running all the functions in the Service with the component variables and child's.
Thank you all... =)
This is best way to refresh data on search .. or dynamic loading
angular-datatables/#/advanced/rerender
datatable refresh
Click on button press table grid refresh
$('#Clienttbl').dataTable().fnClearTable();

angular2 how to get data by JSON and render them in html

I trying to render JSON data,
i do as follows...
#Component({
selector:'free-ip',
templateUrl:'./freeip.component.html'
})
export class FreeIpComponent implements OnInit{
getData:string[];
constructor(private http: FreeIpService){}
getFreeIp(){
this.http.getData()
.subscribe(
data => this.getData
);
}
ngOnInit(){
this.getFreeIp();
}
}
My JSON format...
[{"name":"1(К2)","ipange":"85.143.77.64/26","count":14},
{"name":"1(К2)","ipange":"109.123.184.128/26","count":31},
{"name":" 7","ipange":"109.123.188.128/25","count":60}]
Please help me, how to render data to html?
Thank you.
There is a simpler way render in HTML using the built-in json pipe:
<pre>{{getData | json}}</pre>
Try this:-
freeIpService.ts file:-
import { Injectable } from '#angular/core';
import { Http, URLSearchParams} from '#angular/http';
export class FreeIpService {
constructor(private http: Http) { }
getFreeIp(){
this.http.get('src/assets/data/freeId.json').map(response => response.json()
}
}
FreeIpComponent.ts file:-
import { Component, OnInit } from '#angular/core';
import { FreeIpService } from './freeIpService';
export class FreeIpComponent implements OnInit{
getData:any;
constructor(private FreeIpService: FreeIpService){}
ngOnInit(){
this.FreeIpService.getFreeIp().subscribe(response => { this.getData = response}, err => console.log(err), ()=> console.log(this.getData));
}
Create service file and paste the service.ts code and create a component and paste component.ts code. In assets folder create data folder and in data folder create json file freeId.json file and paste json code in this file.
<tr *ngFor="let item of getData">
<td>{{item.name}}</td>
<td>{{item.ipange}}</td>
<td>{{item.count}}></td>
this is that i wanted)
thank all for your help
You should serialize or deserialize your data when it is responsed
The first, this your http service
get(uri: string) {
return this._http.get("your uri", { headers: "your headers"}).map(this.extractData);
}
private extractData(response: Response) {
let data = response.json();
return data || {}
}
The second, this is function implement in component
getAll() {
this._httpProviderService.get("/api/product_category/GET/categories")
.subscribe(result => {
this.productCategories = result;
});
}
And the last, this is html
<tr *ngFor="let item of productCategories;let rowIndex=index">
<td class="a-center ">
<input type="checkbox" class="" name="table_records">
</td>
<td class="">{{rowIndex+1}}</td>
<td class="">{{item.ID}}</td>
<td class="">{{item.Name}}</td>
<td class="">{{item.Description}}</td>
<td class="">{{item.Status}}</td>
</tr>