I'm engaging with an Angular project. I using ng2-smart-table as a table for my project. as well as some one has connected it for firebase. but i can't understand how its works by look at the code. The affixed code as follows.(I added this ng2-smart-table for patients components of my project)
patients.components.ts
import { Component, OnInit } from '#angular/core';
import { PatientsService } from './patients.service';
import { Patients } from './patients.model';
#Component({
selector: 'ngx-patients',
styles: [],
template: `
<ng2-smart-table
(createConfirm)="addData($event)"
[settings]="settings"
[source]="list"
>
</ng2-smart-table>
`
})
export class PatientsComponent implements OnInit {
list: Patients[] = [];
constructor(private service: PatientsService) {}
ngOnInit() {
this.service.getPatients().subscribe(actionArray => {
let a = actionArray.payload.get('data');
if (a) {
this.list = a;
}
});
}
settings = {
add: {
addButtonContent: '<i class="nb-plus"></i>',
createButtonContent: '<i class="nb-checkmark"></i>',
cancelButtonContent: '<i class="nb-close"></i>',
confirmCreate: true
},
edit: {
editButtonContent: '<i class="nb-edit"></i>',
saveButtonContent: '<i class="nb-checkmark"></i>',
cancelButtonContent: '<i class="nb-close"></i>'
},
delete: {
deleteButtonContent: '<i class="nb-trash"></i>',
confirmDelete: true
},
columns: {
id: {
title: 'ID'
},
name: {
title: 'Full Name'
},
username: {
title: 'User Name'
},
email: {
title: 'Email'
}
}
};
addData(event) {
this.list.push(event.newData);
console.log(this.list);
this.service.addPatient({ data: this.list }).subscribe(next => {
event.confirm.reject();
});
}
}
**patients.service.ts**
import { Injectable } from '#angular/core';
import { AngularFirestore } from '#angular/fire/firestore';
import { Patients } from './patients.model';
import { from } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class PatientsService {
//patients
patients : Patients;
constructor(private firestore: AngularFirestore) { }
/**
* this is for the get informations about patients
*/
getPatients(){
return this.firestore.collection('patients').doc('patientData').snapshotChanges();
}
addPatient(object){
return from(this.firestore.collection('patients').doc('patientData').set(object))
}
}
patients.model.ts
export class Patients {
id: string;
name: string;
username: string;
email: string;
}
what happening by follow keywords
subscribe
push
payload
can anybody help to me.
Angular is built upon a library called RxJs, reactive extensions for JavaScript. Reactive programming is based around observables. This is a concept you really need to learn before you start Angular development. Observables are like arrays of data where the values comes in over time. Subscribing to the observable runs the subscription function each time the observable emits a value down the stream.
This is a concept that cannot be covered in a single StackOverflow answer but some good places to start are.
https://www.learnrxjs.io/
http://reactivex.io/
https://rxmarbles.com/
Related
I want to fetch and display data from Array of Objects.
I have created the parameterized routes.
1. app-routing.module.ts
const routes: Routes = [
{
path: 'all-trades',
component: AllTradesComponent,
},
{
path: 'crop/:name', component: CropComponent
}]
2. Crop.ts
export class Crop {
name: string;
checked: boolean;
subCategory: Subcategory[];
}
export class Subcategory {
id: number;
name: string;
isActive: boolean;
}
3. CropData.ts
Here is my Array of object, I want to access subCategory and display the name on webpage.
for example: When user click on Rice then its should get the result like 'Basmati', 'Ammamore'
OR
When user click on Wheat then its should get the result like 'Durum', 'Emmer'
OR
When user click on Barley then its should get the result like 'Hulless Barley', 'Barley Flakes'
import { Crop } from './Crop';
export const CROP: Crop[] = [
{
name: 'Rice',
checked: true,
subCategory: [
{
id: 1,
name: 'Basmati',
isActive: true,
},
{
id: 2,
name: 'Ammamore',
isActive: true,
},
],
},
{
name: 'Wheat',
checked: true,
subCategory: [
{
id: 1,
name: 'Durum',
isActive: true,
},
{
id: 2,
name: 'Emmer',
isActive: true,
},
],
}, {
name: 'Barley',
checked: true,
subCategory: [
{
id: 1,
name: 'Hulless Barley',
isActive: true,
},
{
id: 2,
name: 'Barley Flakes',
isActive: true,
},
],
}
]
4.1 crop.service.ts
// First I tried this logic
import { Injectable } from '#angular/core';
import { BehaviorSubject } from 'rxjs';
import { skipWhile } from 'rxjs/operators';
import { Crop } from '../shared/Crop';
import { CROP } from '../shared/cropdata';
#Injectable({
providedIn: 'root'
})
export class CropService {
constructor() { }
CropData: Crop
getCrop(name: string): Crop {
return this.CropData.filter((crop) => (crop.name === name))[0];
}
}
4.2 crop.service.ts
// Then I tried this logic
export class CropService {
private selectedCrop= new BehaviorSubject<Crop>(null);
setCrop(crop:Crop){
this.selectedCrop.next(crop);
}
getCrop(){
this.selectedCrop.asObservable().pipe(skipWhile(val=> val === null));
}
}
I failed in both the cases.
5.1 all-trades.components.ts
// First tried using function
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute, Router } from '#angular/router';
import { Crop } from 'src/app/shared/Crop';
import { CropService } from '../crop.service';
#Component({
selector: 'app-all-trades',
templateUrl: './all-trades.component.html',
styleUrls: ['./all-trades.component.css'],
})
export class AllTradesComponent implements OnInit {
constructor(private service: CropService, private router: Router) { }
// Here I tried to make use of function but still its doesnot giving me the desire result
onSelect(selectedCrop:Crop){
this.service.setCrop(selectedCrop);
this.router.navigateByUrl(`crop/${crop.name}`);
}
onChange(event, index, item) {
item.checked = !item.checked;
console.log(index, event, item);
}
ngOnInit(): void { }
}
5.1 all-trades-component.html
<app-header></app-header>
<div
fxLayout="row"
fxLayout.lt-md="column"
fxLayoutAlign="space-between start"
fxLayoutAlign.lt-md="start stretch"
>
<div class="container-outer" fxFlex="20">
<div class="filters">
<section class="example-section">
<span class="example-list-section">
<h1>Select Crop</h1>
</span>
<span class="example-list-section">
<ul>
<li *ngFor="let crop of crops">
<mat-checkbox
[checked]="crop.checked"
(change)="onChange($event, i, crop)"
>
{{ crop.name }}
</mat-checkbox>
</li>
</ul>
</span>
</section>
<div class="content container-outer" fxFlex="80">
<mat-card
class="crop-card"
style="min-width: 17%"
*ngFor="let crop of crops"
[hidden]="!crop.checked"
>
<!-- here i call the function -->
<a (click)="onSelect(crop)" routerLinkActive="router-link-active">
<mat-card-header>
<img
mat-card-avatar
class="example-header-image"
src="/assets/icons/crops/{{ crop.name }}.PNG"
alt="crop-image"
/>
<mat-card-title>{{ crop.name }}</mat-card-title>
<mat-card-subtitle>100 Kgs</mat-card-subtitle>
</mat-card-header>
</a>
<mat-card-content>
<p>PRICE</p>
</mat-card-content>
</mat-card>
</div>
</div>
<app-footer></app-footer>
crop-componet.ts
import { Component, OnInit } from '#angular/core';
import { Subscription } from 'rxjs';
import { Crop } from 'src/app/shared/Crop';
#Component({
selector: 'app-crop',
templateUrl: './crop.component.html',
styleUrls: ['./crop.component.css']
})
export class CropComponent implements OnInit {
service: any;
crop: any;
route: any;
cropservice: any;
sub: Subscription;
constructor() { }
ngOnInit(): void {
// let name = this.route.snapshot.params['name'];
// this.crop = this.cropservice.getCrop(name);
this.sub = this.route.paramMap.subscribe(params => {
let name = params.get("name")
this.crop = this.cropservice.getCrop(name)
})
}
}
7. crop-component.html
<div *ngFor="let category of crop.subCategory">{{category.id}}</div>
This is my eniter code I dont know where I am going wrong please help in fetching data from arrays of object.
[![enter image description here][1]][1]
This is my all-trades.component.html output
When I click Rice I get this as output (Url get change )
[![enter image description here][2]][2]
When I click Wheat I get this
[![enter image description here][3]][3]
And so on....
I just want to display the name of subCategory Array.
Please give me the solution.
[1]: https://i.stack.imgur.com/kxdyj.png
[2]: https://i.stack.imgur.com/OOAtc.png
[3]: https://i.stack.imgur.com/PVcfT.png
On your 4.1 you seem to forget to assign your mock data into your variable
....
import { CROP } from '../shared/cropdata';
#Injectable({
providedIn: 'root'
})
export class CropService {
constructor() { }
CropData: Crop[] = CROP; // Assign the value
getCrop(name: string): Crop {
return this.CropData.filter((crop) => (crop.name === name))[0];
}
}
On your 4.2, you forgot to assign your mock data as well in your BehaviorSubject if you end up using this method. BehaviorSubjects are known to emit initial data
...
import { CROP } from '../shared/cropdata';
export class CropService {
private selectedCrop = new BehaviorSubject<Crop[]>(CROP); // Pass CROP mock data
setCrop(crop: Crop[]) {
this.selectedCrop.next(crop);
}
getCrop() {
this.selectedCrop.asObservable().pipe(skipWhile(val=> val === null));
}
}
Have created a Stackblitz Demo for your reference. You can check the console for the response
In my Angular application I am trying to display the result of a post request in another component (i.e. confirmation page). I wanted to know what would be the best way for this. In my component the code does a post request which posts to the server as follows:
import { Component, OnInit } from '#angular/core';
import { ReactiveFormsModule } from '#angular/forms';
import { FormGroup, FormControl } from '#angular/forms';
import { Validators } from '#angular/forms';
import { FormBuilder } from '#angular/forms';
import { Request } from '../../models/request.model'
import { Router } from '#angular/router';
import { Observable } from 'rxjs';
import { AppComponent } from '../../../app.component';
import { nowService } from '../../services/now.service';
import { HttpClient, HttpEventType, HttpHeaders, HttpRequest, HttpResponse } from '#angular/common/http';
#Component({
selector: 'app-service-request',
templateUrl: './service-request.component.html',
styleUrls: ['./service-request.component.scss']
})
export class ServiceRequestComponent implements OnInit {
public loading = false;
private customer_id = this.appComponent.customer_id;
serviceForm;
u_destination_country = [
{ value: 'Choose an option' },
{ value: 'United Kingdom', },
{ value: 'United States of America', },
{ value: 'Russia', },
{ value: 'Moscow', },
{ value: 'Africa', },
];
users = [
{ id: 'Select an option', },
{ id: '1', },
{ id: '2', },
{ id: '3', },
];
devices = [
{ id: 'Select an option', },
{ id: '1', },
{ id: '2', },
{ id: '3', },
];
constructor(private service: nowService,
private appComponent: AppComponent,
private router: Router,
private http: HttpClient
) {
}
ngOnInit() {
this.serviceForm = new FormGroup({
customer_id: new FormControl(this.customer_id),
si_id: new FormControl('', Validators.required),
u_destination_country: new FormControl(this.u_destination_country[0], Validators.required),
u_short_description: new FormControl('', Validators.compose([
Validators.required,
Validators.minLength(5),
Validators.maxLength(80)
])),
u_message_description: new FormControl(''),
});
}
onSubmit() {
this.http.post("/api/inc",
this.serviceForm.value,
{
headers: new HttpHeaders().set("Content-Type", "application/json")
}
).subscribe((response: any) => {
console.log(response);//On success response
this.router.navigate(['/inc/confirmation']);
}, (errorResponse: any) => {
console.log(errorResponse); //On unsuccessful response
});
if(this.serviceForm.invalid) {
this.serviceForm.setErrors({ ...this.serviceForm.errors, 'required': true });
return;
}
}
}
So what I want to do is display the value of the display_value which is something like:
result: Array(1)
0:
display_name: "number"
display_value: "INC001"
status: "inserted"
table: "incident"
For Angular 7.2.0 and higher:
You can make it by using NavigationExtras built into Angular Router. For this you have to add only two things.
First step:
Update this.route.navigate(['/inc/confirmation']) to this
this.router.navigate(['/inc/confirmation'],{state: {response}});
Second step:
In your second component you can access state by adding this to your code
const state = this.router.getCurrentNavigation().extras.state;
this.response = state.response;
Then you can display it.
For Angular 7 and lower:
First step:
Update this.route.navigate(['/inc/confirmation']) to this
this.router.navigate(['/inc/confirmation'],{queryParams: {value: response.result[0].display_value}});
Second step:
In your second component you can access state by adding this to your code
constructor(private route: ActivatedRoute){}
...
this.value = this.route.snapshot.queryParamMap.get('value');
Then you can display it.
When you don't want to use URL param:
You can create a service with one property
#Injectable({
providedIn: 'root'
})
export class SharedDataService {
public sharedData;
constructor() {
}
}
Then you can set sharedData before you redirect to another route.
constructor(private sharedService: SharedDataService){}
...
this.sharedService.sharedData = response;
this.route.navigate(['/inc/confirmation']);
You can get that data in your second component.
constructor(private sharedService: SharedDataService){}
...
this.response = this.sharedService.sharedData;
I know this question has been asked several times, but problem is that nobody tried to make a some fiddle or show results of code. This is what i have, i need to update values in other component based on value in some other component, but that is not just value,I have call function again in some other component.
I have some component that goes to database and update values, on second hand I have other component that read those values from database from service.
This is example of my code
tasks.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { environment } from '../../environments/environment';
import { Tasks } from './tasks';
#Injectable()
export class TasksProvider {
constructor(private http: HttpClient) { }
createNewTask(name: Name) : Observable<any> {
return this.http.post(environment.apiUri + 'tasks', { name, finished: false },
{ responseType: 'text' });
}
updateTask(id: Id, name: Name, finished: boolean) : Observable<any> {
return this.http.put(environment.apiUri + 'tasks/' + id, { name, finished },
{ responseType: 'text' });
}
getAllTasks(): Observable<Tasks[]> {
return this.http.get(environment.apiUri + 'tasks')
.map<any, Tasks[]>(data => data.map(Tasks.fromObject));
}
}
app.component.html
<app-tasks-list></app-tasks-list>
<app-tasks-add-new></app-tasks-add-new>
As you may see I have not child components, that is my main problem
tasks-list.component.ts
import {Component} from '#angular/core';
import { Tasks } from '../services/tasks';
import { TasksProvider } from '../services/tasks.service';
#Component({
selector: 'app-tasks-list',
templateUrl: './tasks-list.component.html',
styleUrls: ['./tasks-list.component.scss']
})
export class TasksListComponent {
tasks: Array<Tasks>;
constructor(private tasksProvider: TasksProvider) { }
ngOnInit() {
this.getTasksList();
}
displayedColumns: string[] = ['id', 'name', 'finished'];
private getTasksList() {
this.tasksProvider.getAllTasks()
.subscribe(tasks => {
this.tasks = tasks;
});
}
public updateCheckboxValue(id: number, name: string, event: any){
this.tasksProvider.updateTask(id, name, event.checked).subscribe(
result => {},
() => {
alert('Something went wrong');
})
}
}
tasks-add-new.component.ts
import { Component, OnInit, Inject } from '#angular/core';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '#angular/material';
import { Tasks } from '../services/tasks';
import { TasksProvider } from '../services/tasks.service';
export interface DialogData {
name: string;
}
#Component({
selector: 'app-tasks-add-new',
templateUrl: './tasks-add-new.component.html',
styleUrls: ['./tasks-add-new.component.scss']
})
export class TasksAddNewComponent implements OnInit {
ngOnInit() {
}
constructor(public dialog: MatDialog, private tasksProvider: TasksProvider) {}
openDialog(): void {
const dialogRef = this.dialog.open(TasksAddNewDialog, {
width: '250px',
data: {name: this.animal}
});
dialogRef.afterClosed().subscribe(result => {
this.name = result
this.tasksProvider.createNewTask(this.name).subscribe(
result => {},
() => {
alert('Something went wrong');
})
}
}
}
#Component({
selector: 'tasks-add-new-dialog',
templateUrl: 'tasks-add-new-dialog.html'
})
export class TasksAddNewDialog {
constructor(
public dialogRef: MatDialogRef<TasksAddNewDialog>,
#Inject(MAT_DIALOG_DATA) public data: DialogData) {}
onNoClick(): void {
this.dialogRef.close();
}
}
You see now when i call function in tasks-add-new.component.ts like
this.tasksProvider.createNewTask(this.name).subscribe(
result => {},
() => {
alert('Something went wrong');
})
I need to call again function in tasks-list.component.ts
private getTasksList() {
this.tasksProvider.getAllTasks()
.subscribe(tasks => {
this.tasks = tasks;
});
}
Does any body have idea how i can do that the best practice?
On of the possible approach is to use Subjects.
1) Store task list on the service and provide subscribable Subject
private tasks: Array<Task>;
public $tasks: BehaviorSubject<Array<Task>>;
constructor(private http: HttpClient) {
this.$tasks = new BehaviorSubject([]);
...
}
getAllTasks() {
this.http.get(environment.apiUri + 'tasks')
.subscribe(data => {
this.tasks = data;
this.$tasks.next(this.tasks);
});
}
updateTask(params) {
this.http.post(/* params */).subscribe((task) => {
this.tasks = this.tasks.map(t => t.id !== task.id ? t : task);
this.$tasks.next(this.tasks);
});
}
createTask(...) {
// again, do a request, update this.tasks and call $tasks.next
...
}
2) Make one service Subject subscription on the component instead of multiple service methods Observable listeners and update component's list automatically each time the service source has been changed
tasks: Array<Tasks>;
constructor(private tasksProvider: TasksProvider) {
this.tasksProvider.$tasks.subscribe(tasks => this.tasks = tasks);
}
ngOnInit() {
this.tasksProvider.getAllTasks();
}
public updateCheckboxValue(id: number, name: string, event: any){
this.tasksProvider.updateTask(id, name, event.checked);
}
I am trying to get my JSON response from the HttpClient service into an array so that I can loop through using *ngFor in my html. I've tried using "this" to loop through but *ngFor will not accept it. Below is the code for my service.ts component and the main component.ts.
I just need some way to convert an array from "resp.body" into an exportable Array to be used for string interpolation in the html. Any help would be much appreciated!
races.component.ts
import { Component, OnInit } from '#angular/core';
import {Race, RacesService} from './races.service';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'dh-races',
templateUrl: './races.component.html',
providers: [ RacesService ],
styleUrls: ['./races.component.scss']
})
export class RacesComponent {
error: any;
headers: string[];
race: Race;
raceM: any[];
constructor(private racesService: RacesService) {
var raceM = [];
var raceArray = [];
this.racesService.getRaceResponse()
.subscribe(resp => {
raceArray.push(resp.body);
for (let obj of raceArray) {
for (let i in obj) {
raceM.push({
"ID": obj[i].id + ",",
"Date": obj[i].activityStartDate,
"RaceName": obj[i].assetName,
"Website": obj[i].website
})
}
console.log(raceM);
return raceM;
}
});
}
races.service.ts
#Injectable()
export class RacesService {
constructor(private httpClient: HttpClient) { }
getRace() {
return this.httpClient.get(activeApiURL).pipe(
retry(3),
catchError(this.handleError)
);
}
getRaceResponse(): Observable<HttpResponse<Race>> {
return this.httpClient.get<Race>(
activeApiURL, {
observe: 'response'
});
}
To fix the issue, you need to create an interface that matches the data you get from the server, I will call this interface IRace.
Then in the component I will create a variable named races, I will assign the returned value from the server response i.e. resp.body to the races variable.
I'd change the service to look like this:
export interface IRace {
// Your response from server object's properties here like so:
id: Number;
assetName: string;
...
}
export class RacesService {
constructor(private httpClient: HttpClient) { }
getRace() {
return this.httpClient.get(activeApiURL).pipe(
retry(3),
catchError(this.handleError)
);
}
getRaceResponse(): Observable<HttpResponse<Array<Race>>> {
return this.httpClient.get<Array<Race>>(
activeApiURL, {
observe: 'response'
});
}
}
Finally, I'd change the race component to this:
import { Component, OnInit } from '#angular/core';
import { Race, RacesService, IRace } from './races.service';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'dh-races',
templateUrl: './races.component.html',
providers: [ RacesService ],
styleUrls: ['./races.component.scss']
})
export class RacesComponent {
error: any;
headers: string[];
races: IRace[];
constructor(private racesService: RacesService) {
this.racesService.getRaceResponse()
.subscribe(resp => {
this.races = resp.body;
});
}
}
I hope this helps.
i,ve been pulling hair with what I tought was going to be a simple code. I admit that i am quite new to typescript and learning as I go but more familiar with javascript.
I am basically creating a SPA (Single Page Application) using AG-GRID as my maine component. I have a service which pulls data from a REST connection (currently using JSON server to mimick that) and will share that data across multiple components. AG-GRID seems to be the only component refusing to work correctly at the moment. I am getting the error below.
Ive been scavaging the internet for solution for a few weeks now but cant find an exmaple that matches my situation. Would anyone here know what to do with the error below?
Console Error:
error TS2345: Argument of type '(data: Incident_Model) => Incident_Model' is not assignable to parameter of type '(value: Incident_Model[]) => void'.
Types of parameters 'data' and 'value' are incompatible.
Type 'Incident_Model[]' is not assignable to type 'Incident_Model'.
Property 'id' is missing in type 'Incident_Model[]'.
Angular interface:
export class Incident_Model {
id: number;
Incident: string;
status: string;
}
Angular service:
import { Injectable } from '#angular/core';
import { environment } from '../../environments/environment';
import { HttpClient } from "#angular/common/http";
import { Observable } from 'rxjs/Observable';
import { Incident_Model } from './incident_model';
const BackEnd_URL = environment.BackEnd_URL;
#Injectable()
export class BackEndService {
constructor(private http: HttpClient ) { }
getAllIncidents(): Observable<Incident_Model[]> {
return this.http.get<Incident_Model[]>(BackEnd_URL + '/Incidents');
}
}
Angular Component:
ngOnInit() {this.backendservice.getAllIncidents().subscribe( data => this.gridOptions.api.setRowData = data )}
Updated with code in comment below - 11h37 - 2018-02-07:
Here is the full component code just in case someone can spot something im missing:
import { Component, OnInit } from '#angular/core';
import { GridOptions } from "ag-grid";
import { BackEndService } from '../../Shared/back-end.service';
import { Incident_Model } from '../../Shared/incident_model';
#Component({
selector: 'app-archive',
templateUrl: './archive.component.html',
styleUrls: ['./archive.component.css']
})
export class ArchiveComponent implements OnInit {
private gridOptions: GridOptions;
constructor(private backendservice: BackEndService) {
var gridSize = 8;
var rowHeight = gridSize * 6;
var headerHeight = gridSize * 7;
this.gridOptions = <GridOptions>{
enableFilter: true,
enableColResize: true,
enableSorting: true,
pagination: true,
paginationPageSize:25,
animateRows: true,
headerHeight: headerHeight,
rowHeight:rowHeight
};
this.gridOptions.columnDefs = [
{
headerName: "Headname here",
children:[
{
headerName: "id",
field: "id",
width: 165,
filterParams: { applyButton: true, clearButton:true }
},
{
headerName: "Incident",
field: "Incident",
width: 450,
filterParams: { applyButton: true, clearButton:true }
},
{
headerName: "status",
field: "status",
width: 110,
filterParams: { applyButton: true, clearButton:true }
}
];
}
ngOnInit() {this.backendservice.getAllIncidents().subscribe(data => this.gridOptions.api.setRowData(data)) }
}
For one, data for should be passed as a parameter instead of an assignement:
this.backendservice.getAllIncidents().subscribe(data => this.gridOptions.api.setRowData(data));