I have a question about a get and put request using angular.
I know how I can do a get or put request when I for example click on a button. For that, I just have to bind my request to the button. But now I want to be able to make a get request for example without some button. that means ich enters for example a barcode and just clicks on my keyboard on entering and releases my get request.
A normal code for a get look for example like:
this.codeService.getBarcode(barcode).subscribe(_=>
...
)
my question is what do I have to do in the subscribe to be able to do this get request if I don't have some button to click
If you want to get data when you load the app without clicking but in OnInit time.
You can write direct in your component but that is not a clean code.
You better write a service which will hold get and put.
Here is a little example.
Here you have get, post, put and delete
export class EmployeeService {
private baseUrl = "http://localhost:8081/rest/user";
constructor(private http: HttpClient) { }
getEmployee(id: number): Observable<any> {
return this.http.get(`${this.baseUrl}/${id}`);
}
createEmployee(employee: object): Observable<object> {
return this.http.post(`${this.baseUrl}`, employee);
}
updateEmployee(id: number, value: any): Observable<object> {
return this.http.put(`${this.baseUrl}/${id}`, value);
}
deleteEmployee(id: number): Observable<any> {
return this.http.delete(`${this.baseUrl}/${id}`);
}
getEmployeesList(): Observable<any> {
return this.http.get(`${this.baseUrl}`);
}
}
You need then to add HttpClientModule in the app.module.ts
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
HttpClientModule <-- This here
],
You can have an interface like this.
export class Employee {
id: number;
name: string;
age: number;
}
Your component ts
export class EmployeeListComponent implements OnInit {
employees: Observable<Employee[]>;
constructor(private employeeService: EmployeeService,
private router: Router) {}
ngOnInit() {
this.reloadData();
}
reloadData() {
this.employees = this.employeeService.getEmployeesList();
}
deleteEmployee(id: number) {
this.employeeService.deleteEmployee(id)
.subscribe(data => console.log(data, id));
this.reloadData();
}
employeeDetails(id: number) {
this.router.navigate(['details', id]);
}
}
Your component HTML
<div class="panel panel-primary">
<div class="panel-heading">
<h2>Employee List</h2>
</div>
<div class="panel-body">
<table class="table table-striped">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
<th>Description</th>
<th>City</th>
<th>Extra</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let employee of employees | async">
<td>{{employee.name}}</td>
<td>{{employee.age}}</td>
<td><button (click)="deleteEmployee(employee.id)" class="btn btn-danger">Delete</button>
<button (click)="employeeDetails(employee.id)" class="btn btn-info" style="margin-left: 10px">Details</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
Related
I have products.components.ts class, where I am getting Json data in this.Getdata
ngOnInit() {
this._service.getProducts(this.baseUrl)
.subscribe(data => {
this.Getdata=data
this.products=data
alert(JSON.stringify(this.Getdata));
});
This Josn data I want to bind in products.components.html class Table
<p>
Product List
</p>
<table>
<th>Id</th> <th>Name</th> <th> Country</th> <th>Actions</th>
<tr *ngFor="let lst of products; let i = index" border="1">
<td>{{i+1}}</td><td>{{lst.id}}</td><td>{{lst.employee_name}}</td> <td>Edit</td>
</tr>
</table>
The above code is not working. Only alert displaying. How can I bind data to table?
This is my Json data
[{"id":"1","employee_name":"amit","employee_salary":"0","employee_age":"0","profile_image":""},{"id":"247793","employee_name":"Ana","employee_salary":"123","employee_age":"123","profile_image":""},{"id":"247856","employee_name":"Joseph Beltran","employee_salary":"1000","employee_age":"23","profile_image":""},{"id":"247982","employee_name":"testyeyyeye1","employee_salary":"123","employee_age":"23","profile_image":""},{"id":"248007","employee_name":"test100","employee_salary":"123","employee_age":"23","profile_image":""},{"id":"248038","employee_name":"Hendry","employee_salary":"61888","employee_age":"26","profile_image":""}]
Model class
export class Productlist {
id: string;
employee_name: string;
employee_salary: string;
employee_age: string;
profile_image: string;
}
Instead of subscribing to the Observable, consider storing it in a property and then unwrapping it in the template using the async pipe.
If you consider that, then you can significantly reduce your Component to this:
import { Component } from '#angular/core';
import { Observable } from 'rxjs';
import { EmployeeService } from './employee.service';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
employees$: Observable<Array<any>> = this.employeeService.getEmployees();
constructor(private employeeService: EmployeeService) {}
}
And in your Template:
<p>
Employee List
</p>
<table border="1">
<thead>
<th>Id</th>
<th>Name</th>
<th> Country</th>
<th>Actions</th>
</thead>
<tbody>
<tr *ngFor="let employee of employees$ | async; let i = index">
<td>{{i+1}}</td>
<td>{{employee.id}}</td>
<td>{{employee.employee_name}}</td>
<td>Edit</td>
</tr>
</tbody>
</table>
Here's a Working Sample Demo Code for your ref.
PS: Consider naming your properties and methods appropriately. If you're working with employees, then it doesn't really make sense to name properties and methods as products.
You can also use
const myobject= JSON.parse(yourjsonvalue);
You will get the object in myobject and now you can loop through with simple ngFor.
I got it this way
export class ProductsComponent implements OnInit {
public Getdata;
products:Productlist[];
constructor(private employeeService: ProductService) {}
ngOnInit() {
this.employeeService.getProducts(this.baseUrl)
.subscribe((data:any) => {
this.products=data;
});
}
}
I am using Angular 8, and am querying an endpoint to get an object. When I call it via Advanced REST Client, I get the following returned JSON:
GET: http://localhost:8090/curso_conductor/
Returns:
{
"dato": [{
"ID_CURSO_CONDUCTOR": 1,
"F_INICIO": "2019-09-19T05:00:00.000+0000",
"F_FIN": "2019-12-20T05:00:00.000+0000",
"ESTADO": "1",
"CARNET_C": "l584f",
"F_CADUCIDAD": "2022-06-20T05:00:00.000+0000",
"F_EMISION": "2017-06-20T05:00:00.000+0000",
"ID_CURSO": 1,
"ID_PERSONA": 3
},
{
"ID_CURSO_CONDUCTOR": 2,
"F_INICIO": "2019-08-20T05:00:00.000+0000",
"F_FIN": "2019-12-20T05:00:00.000+0000",
"ESTADO": "1",
"CARNET_C": "8574h",
"F_CADUCIDAD": "2023-04-05T05:00:00.000+0000",
"F_EMISION": "2017-04-08T05:00:00.000+0000",
"ID_CURSO": 1,
"ID_PERSONA": 5
},
{
"ID_CURSO_CONDUCTOR": 3,
"F_INICIO": "2019-10-09T05:00:00.000+0000",
"F_FIN": "2019-12-10T05:00:00.000+0000",
"ESTADO": "1",
"CARNET_C": "2685f",
"F_CADUCIDAD": "2022-08-10T05:00:00.000+0000",
"F_EMISION": "2017-08-09T05:00:00.000+0000",
"ID_CURSO": 1,
"ID_PERSONA": 6
}
],
}
In Angular 8, I then have a service, where I want to make an http call to to the endpoint that will return the above JSON.
getCursoConductor(): Observable<Curso_Conductor[]>{
return this.http.get<Curso_Conductor[]>(this.curso_conductores).pipe();
}
As you can see the result needs to be put into the Curso_Conductor object.
And my model is this:
export class Curso_Conductor {
dato: Dato[];
}
export class Dato {
ID_CURSO_CONDUCTOR: number;
F_INICIO: string;
F_FIN: string;
ESTADO: string;
CARNET_C: string;
F_CADUCIDAD: string;
F_EMISION: string;
ID_CURSO: number;
ID_PERSONA: number;
}
My question is how do I put the data into the Curso_conductorComponent.html?
This is my component.html:
<table class="table table-hover">
<thead>
<tr>
<th>ID</th>
<th>FECHA INICIO</th>
<th>FECHA FIN</th>
<th>ESTADO</th>
<th>Nro CARNET</th>
<th>FECHA CADUCIDAD</th>
<th>FECHA EMISION</th>
<th>IDCURSO</th>
<th>IDPERSONA</th>
<th colspan="2">OPCION</th>
</tr>
</thead>
<tbody>
<tr *ngIf="curso_conductoresObservable | async as curso_conductores else empty">
<tr *ngFor="let curso_conductor of curso_conductores">
<td>{{curso_conductor.id_curso_conductor}}</td>
<td>{{curso_conductor.f_inicio}}</td>
<td>{{curso_conductor.f_fin}}</td>
<td>{{curso_conductor.estado}}</td>
<td>{{curso_conductor.carnet_c}}</td>
<td>{{curso_conductor.f_caducidad}}</td>
<td>{{curso_conductor.f_emision}}</td>
<td>{{curso_conductor.id_curso}}</td>
<td>{{curso_conductor.id_persona}}</td>
<td><button class="btn btn-warning" (click)="Editar(curso_conductor)">Editar</button></td>
<td><button class="btn btn-danger" (click)="Eliminar(curso_conductor)">Eliminar</button></td>
</tr>
</tbody>
</table>
And my component.ts:
curso_conductores: Curso_Conductor[];
constructor(private service: ServiceService, private router: Router) { }
#Input() nombre = '';
ngOnInit() {
this.service.getCursoConductor()
.subscribe(data => {this.curso_conductores=data });
}
I'm getting this error:
Cannot find a differ supporting object
'[object Object]' of type 'object'. NgFor only supports binding to
Iterables such as Arrays.
There are a few issue with your implementation.
The array that you get from the API is present on the dato property. You ideally you should be creating an interface for that:
export interface ApiResponse {
dato: Curso_Conductor[];
}
export interface Curso_Conductor {
ID_CURSO_CONDUCTOR: number;
F_INICIO: string;
F_FIN: string;
ESTADO: string;
CARNET_C: string;
F_CADUCIDAD: string;
F_EMISION: string;
ID_CURSO: number;
ID_PERSONA: number;
}
You'll then have to update your service to reflect the type of data that you're expecting. I'm also changing the name of the service as ServiceService makes no sense at all:
import { Injectable } from "#angular/core";
import { HttpClient } from "#angular/common/http";
import { Observable } from "rxjs";
import { ApiResponse } from "./models/conductor.model";
#Injectable()
export class DataService {
curso_conductores = "assets/data.json";
constructor(private http: HttpClient) {}
getCursoConductor(): Observable<ApiResponse> {
return this.http.get<ApiResponse>(this.curso_conductores);
}
}
You're subscribeing to the Observable in your Component and you're also using an async pipe. Which automatically does the unwrapping for you. So just stick to using the async pipe in the template. That's also what's the recommended way:
import { Component } from "#angular/core";
import { Curso_Conductor, ApiResponse } from "./models/conductors.model";
import { DataService } from "./data.service";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";
#Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
curso_conductores$: Observable<Array<Curso_Conductor>>;
constructor(private service: DataService) {}
ngOnInit() {
this.curso_conductores$ = this.service.getCursoConductor()
.pipe(
map((apiResponse: ApiResponse) => apiResponse.dato)
);
}
}
Finally, the Object fields are all in upper case but you're using them as lower case in the template. That needs to be fixed as well:
<table class="table table-hover" border="1">
<thead>
<tr>
<th>ID</th>
<th>FECHA INICIO</th>
<th>FECHA FIN</th>
<th>ESTADO</th>
<th>Nro CARNET</th>
<th>FECHA CADUCIDAD</th>
<th>FECHA EMISION</th>
<th>IDCURSO</th>
<th>IDPERSONA</th>
<th colspan="2">OPCION</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let curso_conductor of (curso_conductores$ | async) as curso_conductores">
<td>{{curso_conductor.ID_CURSO_CONDUCTOR}}</td>
<td>{{curso_conductor.F_INICIO}}</td>
<td>{{curso_conductor.F_FIN}}</td>
<td>{{curso_conductor.ESTADO}}</td>
<td>{{curso_conductor.CARNET_C}}</td>
<td>{{curso_conductor.F_CADUCIDAD}}</td>
<td>{{curso_conductor.F_EMISION}}</td>
<td>{{curso_conductor.ID_CURSO}}</td>
<td>{{curso_conductor.ID_PERSONA}}</td>
<td><button class="btn btn-warning" (click)="Editar(curso_conductor)">Editar</button></td>
<td><button class="btn btn-danger" (click)="Eliminar(curso_conductor)">Eliminar</button></td>
</tr>
</tbody>
</table>
Hope this clears this up for you.
Here's a Working Sample StackBlitz for your ref.
Are you sure the return type is Curso_Conductor[]? It seems like Curso_Conductor.
Try this,
getCursoConductor(): Observable<Curso_Conductor>{
return this.http.get<Curso_Conductor>(this.curso_conductores).pipe();
}
...
curso_conductore: Curso_Conductor;
constructor(private service: ServiceService, private router: Router) { }
#Input() nombre = '';
ngOnInit() {
this.service.getCursoConductor().subscribe(data => {this.curso_conductore=data });
}
and in html
...
<tr *ngFor="let d of curso_conductore.dato.dato">
<td>{{d.id_curso_conductor}}</td>
<td>{{d.f_inicio}}</td>
...
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();
}
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.
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();
}