Angular - Show spinner during search bar api request - html

I'm having trouble implementing the display of a loading spinner once the user inserts a search term in the search bar. Once I detect a change on my search term property, an API request is done to fill the lists in my view with the corresponding data and I want to show my spinner during this process.
Here is my .ts:
#Component({
selector: 'app-orders-list',
templateUrl: './orders-list.component.html',
styleUrls: ['./orders-list.component.css'],
})
export class OrdersListComponent implements OnChanges, AfterViewInit{
#Input() ordersWithSlots: Order[] = [];
#Input() ordersWithNoSlots: Order[] = [];
#Input() timelinesWithSlots: string[] = [];
#Input() timelinesWithNoSlots: string[] = [];
#Input() currentTabIndex: number;
#Input() searchTerm: string;
filteredSlotsOrders: Order[] = [];
filteredNoSlotsOrders: Order[] = []
filteredSlotsTimelines: string[] = [];
filteredNoSlotsTimelines: string[] = [];
showSpinner = false;
constructor(
private apiManager: ApiManagerService,
private ordersService: OrdersManagerService
) {}
ngOnChanges(changes: SimpleChanges): void {
// searchTerm comes from parent component, if it changes then a new search is active
if (changes.searchTerm) {
if(changes.searchTerm.currentValue !== changes.searchTerm.previousValue){
if(changes.searchTerm.currentValue === "") {
this.filteredSlotsOrders = [...this.ordersWithSlots];
this.filteredNoSlotsOrders = [...this.ordersWithNoSlots];
this.filteredSlotsTimelines = [...this.timelinesWithSlots];
this.filteredNoSlotsTimelines = [...this.timelinesWithNoSlots];
}
else{
this.getOrdersBySearchTerm(); // want to show a spinner while this task is running
}
}
}
...
}
getOrdersBySearchTerm(){
if(this.currentTabIndex === 0){
this.apiManager.fetchOrdersBySearchTerm("status=PENDING&status=FULFILLED&only_slots=true", this.searchTerm).subscribe(orders => {
const loadedOrders = orders;
this.filteredSlotsOrders = loadedOrders.results;
});
this.apiManager.fetchOrdersBySearchTerm("status=PENDING&status=FULFILLED", this.searchTerm).subscribe(orders => {
const loadedOrders = orders;
this.filteredNoSlotsOrders = this.ordersService.filterOrders(loadedOrders.results, OrderStatus.PENDING, false);
this.filteredNoSlotsOrders = [...this.filteredNoSlotsOrders, ...this.ordersService.filterOrders(loadedOrders.results, OrderStatus.PROCESSED, false)]
});
...
}
And here is my .html:
<app-loading-spinner [hidden]="showSpinner !== true"></app-loading-spinner>
<div [hidden]="showSpinner === true">
<!-- the actual view and data is here -->
</div>
Since the view exists and has data before we can do a search on the search bar, I can't do something like starting the spinner set to true in ngOnInit and then setting it to false after this.getOrdersBySearchTerm() is called.
What can I do to only show the spinner in this particular search situation?
Thanks in advance.

How about:
getOrdersBySearchTerm(){
this.showSpinner = true;
if(this.currentTabIndex === 0){
this.apiManager.fetchOrdersBySearchTerm("status=PENDING&status=FULFILLED&only_slots=true", this.searchTerm).subscribe(orders => {
const loadedOrders = orders;
this.filteredSlotsOrders = loadedOrders.results;
this.showSpinner = false;
});
this.apiManager.fetchOrdersBySearchTerm("status=PENDING&status=FULFILLED", this.searchTerm).subscribe(orders => {
this.showSpinner = false;
const loadedOrders = orders;
this.filteredNoSlotsOrders = this.ordersService.filterOrders(loadedOrders.results, OrderStatus.PENDING, false);
this.filteredNoSlotsOrders = [...this.filteredNoSlotsOrders, ...this.ordersService.filterOrders(loadedOrders.results, OrderStatus.PROCESSED, false)]
});
...
}
<ng-template #loading>
<app-loading-spinner></app-loading-spinner>
</ng-template>
<div *ngIf="!showSpinner; else loading">
<!-- the actual view and data is here -->
</div>

Related

Angular Trouble Emptying Array

Hell, I have an e-commerce application in which I am trying to empty the shopping cart after payment is successful, no matter what I have tried the array will not empty. I have tried cartItems.length = 0,
cartItems = [] as well as splice. I must be missing something. Code snippet below I will walk you through it.
This is my Model
import { Product } from './product';
export class CartItem {
id: number;
productId: number;
productName: string;
qty: number;
price: number;
size:string;
imageUrl:string;
constructor(id:number, size:string,
product:Product, qty= 1) {
this.id = id;
this.productId = product.id;
this.price = product.price;
this.size = size;
this.productName = product.name;
this.qty = qty;
this.imageUrl = product.imageUrl;
}
}
This is my car service as you can see I remove and add to cart as well as get cart items, there is no problem here. The remove and add are button clicks on html
export class CartService {
product: any;
cartItem: CartItem[] = [];
cartUrl = 'http://localhost:4000/cart';
constructor(private http: HttpClient, private router: Router,
private route: ActivatedRoute) {
}
getCartItems(): Observable<CartItem[]> {
return this.http.get<CartItem[]>(cartUrl).pipe(
map((result: any[]) => {
let cartItems: CartItem[] =[];
for(let item of result) {
cartItems.push( new CartItem(item.id, item.size,
item.product, item.imageUrl ));
}
return cartItems;
})
);
}
addProductToCart(product:Product):Observable<any>{
return this.http.post(cartUrl, {product});
}
RemoveProductFromCart(id:number):Observable<void>{
//this.cartItems.splice(index,1)
alert("show deleted item");
return this.http.delete<CartItem[]>(`${this.cartUrl}/${id}`)
.pipe(catchError(_err => of (null))
);
}
buttonClick() {
const currentUrl = this.router.url;
this.router.navigateByUrl('/', {skipLocationChange:
true}).then(() => {
this.router.navigate([currentUrl]);
});
//alert("Should Reload");
}
addPurseToCart(product:Product):Observable<any>{
return this.http.post(cartUrl, {product})
}
}
Here is the checkout component, I injected the cart component so I could call the the empty cart function which resides in the cart component. I did import the CartComponent. Check out is based on cart. When the cart is emptied so should checkout
#Component({
providers:[CartComponent], //injected CartComponent
selector: 'app-checkout',
templateUrl: './checkout.component.html',
styleUrls: ['./checkout.component.scss']
})
export class CheckoutComponent implements OnInit {
// #ViewChild(CartComponent) // #ViewChild(CartItemComponent) cartitemComponent: CartItemComponent
cartComponent: CartComponent
#Input() product: CartItem;
#Input() cartItem: CartItem;
cartUrl = 'http://localhost:4000/cart';
size;
cartItems = [];
cartTotal = 0;
itemTotal = 0;
shipping = 8.00;
estimatedTax = 0;
myValue: any;
constructor(private msg: MessengerService, private route:
ActivatedRoute,
private router: Router, private
cartService:CartService,
private productService: ProductService, private
comp:CartComponent) {}
ngOnInit() {
this.loadCartItems();
}
}
loadCartItems(){
this.cartService.getCartItems().subscribe((items:
CartItem[]) => {
this.cartItems = items;
this.calcCartTotal();
this.calNumberOfItems();
})
}
calcCartTotal() {
this.cartTotal = 0;
this.cartItems.forEach(item => {
this.cartTotal += (item.qty * item.price);
})
this.cartTotal += this.shipping;
this.myValue = this.cartTotal
render(
{
id:"#paypal-button-container",
currency: "USD",
value: this.myValue,
onApprove: (details) =>{
alert("Transaction Suceessfull")
console.log(this.myValue);
this.comp.handleEmptyCart();
}
}
);
}
calNumberOfItems(){
console.log("Trying to get tolal items")
this.itemTotal = 0;
this.cartItems.forEach(item => {
this.itemTotal += item.qty;
})
}
}
cart component
export class CartComponent implements OnInit {
#Input() product: CartItem;
#Input() cartItem: CartItem;
//items: CartItem [] =[];
cartUrl = 'http://localhost:4000/cart';
val;
size;
cartItems = [];
cartTotal = 0
itemTotal = 0
constructor(private msg: MessengerService, private
cartService:CartService, private productService:
ProductService, private formBuilder:FormBuilder, private
_data:AppserviceService, private router:Router) { }
ngOnInit(): void {
this.handleSubscription();
this.loadCartItems();
}
handleSubscription(){
this.msg.getMsg().subscribe((product: Product) => {
})
}
loadCartItems(){
this.cartService.getCartItems().subscribe((items:
CartItem[]) => {
this.cartItems = items;
console.log("what is in cartItems" + this.cartItems)
console.log("What does this property hold" +
this.cartItem)
this.calcCartTotal();
this.calNumberOfItems();
})
}
calcCartTotal() {
this.cartTotal = 0
this.cartItems.forEach(item => {
this.cartTotal += (item.qty * item.price)
})
}
calNumberOfItems(){
console.log("Trying to get tolal items")
this.itemTotal = 0
this.cartItems.forEach(item => {
this.itemTotal += item.qty
})
}
handleEmptyCart(){
alert("Hit Empty Cart");
/*here I get the cart items to see what is in the array
and try to empty, it does show tow objects in the
array*/
this.cartService.getCartItems().subscribe((items:
CartItem[]) => {
this.cartItems = items;
this.cartItems.length=0
// this.cartItems = [];
console.log("what is in cartItems" + this.cartItems)
})
}
}
I have used different approaches trying to empty the cart nothing works. It makes me think I'm stepping on something or somehow creating events calling the loadCartItems to many times not sure but according to my research one of these approaches should work. If someone can please help me out I'm stuck. I would greatly appreciate it.
Short answer: run change detection ChangeDetectorRef.detectChanges()
Long answer:
You need to understand how angular works.
Lets assume simple example:
<div id="val">{{val}}</div><button (click)="val++">Increase<div>
So when u click button variable changes, but who changes actual #val div content? Answer is that Angular uses zone.js to patch/change a lot of functions to run Angular change detection after most of JS events (you can control type of this events to include/exclude some of them). Also Promise is patched same way, thats why after some Promise is resolve change detection is run.
However, here you run some render method with onApprove callback which is probably some 3rd party library (?) and zone.js is not aware of it (https://angular.io/guide/zone#ngzone-run-and-runoutsideofangular). And though running detectChanges gonna help u, u better re-write your code, so onApprove is always in Angular zone and u never gonna face similar bugs in future when using this method.

Independent row buttons mat-table

I have a mat-table where each row represents a audio recording for a call. At the end of each row, there is a play button which plays the respective audio file when clicked. However, when I click any play button, the correct audio file plays but all the play buttons change to stop buttons. Here is a snippet of the html:
<!-- audio display -->
<ng-container matColumnDef="isPlaying">
<mat-header-cell *matHeaderCellDef>Playing</mat-header-cell>
<mat-cell *matCellDef="let recording">
<button mat-button (click)="playToggle(recording)" [disabled]="state?.error" *ngIf="!state?.playing">
<mat-icon mat-list-icon>play_arrow</mat-icon>
</button>
<button mat-button (click)="pause()" *ngIf="state?.playing">
<mat-icon mat-list-icon>pause</mat-icon>
</button>
</mat-cell>
</ng-container>
recordings.component.ts
#Component({
selector: 'recordings',
templateUrl: './recordings.component.html',
styleUrls: ['./recordings.component.scss'],
encapsulation: ViewEncapsulation.None,
animations: fuseAnimations
})
export class RecordingsComponent implements OnInit {
// Class Variables
recordingPlaying = false;
buttonValue = 'Play Recording';
displayColumns: string[] = ['date', 'time'];
dataSource: MatTableDataSource < Recording > ;
currentUser: BehaviorSubject < UserModel > ;
dataLoading = true;
recordings: Recording[];
recording: Recording;
state: RecordingStreamState;
currentFile: any = {};
#ViewChild(MatPaginator) paginator: MatPaginator;
#ViewChild(MatSort) sort: MatSort;
#Input()
telephone: string;
// Private
private audio = new Audio();
private _unsubscribeAll: Subject < any > ;
constructor(
private _recordingsService: RecordingsService,
private _usersService: UserService,
private _matSnackBar: MatSnackBar,
private _fuseSidebarService: FuseSidebarService,
private _matDialog: MatDialog
) {
// Set the defaults
this._unsubscribeAll = new Subject();
}
ngOnInit(): void {
this.currentUser = this._usersService.user;
this.loadRecordings();
// listen to stream state
this._recordingsService.getState().subscribe(state => {
this.state = state;
console.log('this.state: ' + JSON.stringify(this.state));
});
}
public loadRecordings(): void {
this._recordingsService.getRecordings(this.telephone).then(data => {
this.recordings = data;
});
this._recordingsService.onRecordingClick
.subscribe((recordings: Recording[]) => this.handleRecordings(recordings),
err => this.handleRecordingsError(err)
);
}
private handleRecordings(recordings: Recording[]): void {
this.dataLoading = false;
this.dataSource = new MatTableDataSource(recordings);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
private handleRecordingsError(err): void {
console.error(err);
// this.alertService.error("Problem loading contacts!");
}
playToggle(recording): void {
// TODO: (remove) if this is the reocrding already playing, pause, else play
if (recording === this.recording) {
this.pause();
this.recording = null;
} else {
this.recording = recording;
console.log('this.recording: ' + JSON.stringify(this.recording));
if (this.recording === undefined) {
console.log('could not find recording.');
} else {
this.playStream(this.recording.url);
}
}
}
playStream(url): void {
// subscribes to playStream in our service and starts listening to media events
// like canplay, playing etc. This should be done in the stateChange object
// but we use this method to start the observable and audio playback
this._recordingsService.playStream(url).subscribe(events => {
});
}
pause(): void {
this._recordingsService.pause();
}
play(): void {
this._recordingsService.play();
}
stop(): void {
this._recordingsService.stop();
}
}
recordings.service.ts
#Injectable()
export class RecordingsService implements Resolve < any > {
// Class variables
routeParams: any;
recordings: Recording[];
onRecordingClick: BehaviorSubject < any > ;
private stop$ = new Subject();
private audioObj = new Audio();
audioEvents = [
'ended',
'error',
'play',
'playing',
'pause',
'timeupdate',
'canplay',
'loadedmetadata',
'loadstart',
];
// gets from the interface we created
private state: RecordingStreamState = {
playing: false,
readableCurrentTime: '',
readableDuration: '',
duration: undefined,
currentTime: undefined,
canplay: false,
error: false,
};
private stateChange: BehaviorSubject < RecordingStreamState > = new BehaviorSubject(
this.state
);
// tslint:disable-next-line:typedef
private streamObservable(url) {
console.log('in streamObservable in service');
// tslint:disable-next-line:no-unused-expression
return new Observable(observer => {
// Play audio
this.audioObj.src = url;
this.audioObj.load();
this.audioObj.play();
// a way for the observer to react to items the observable emits
const handler = (event: Event) => {
this.updateStateEvents(event);
observer.next(event);
};
this.addEvents(this.audioObj, this.audioEvents, handler);
return () => {
// stop playing
this.audioObj.pause();
this.audioObj.currentTime = 0;
// remove event listeners
this.removeEvents(this.audioObj, this.audioEvents, handler);
};
});
}
private addEvents(obj, events, handler): void {
events.forEach(event => {
obj.addEventListener(event, handler);
});
}
private removeEvents(obj, events, handler): void {
events.forEach(event => {
obj.removeEventListener(event, handler);
});
}
// how to handle the different events , recording: Recording
private updateStateEvents(event: Event): void {
console.log('event_type: ' + event.type);
switch (event.type) {
case 'canplay':
this.state.duration = this.audioObj.duration;
this.state.readableDuration = this.formatTime(this.state.duration);
this.state.canplay = true;
break;
case 'playing':
this.state.playing = true;
break;
case 'pause':
this.state.playing = false;
break;
case 'timeupdate':
this.state.currentTime = this.audioObj.currentTime;
this.state.readableCurrentTime = this.formatTime(
this.state.currentTime
);
break;
case 'error':
this.resetState();
this.state.error = true;
break;
}
this.stateChange.next(this.state);
}
private resetState(): void {
this.state = {
playing: false,
readableCurrentTime: '',
readableDuration: '',
duration: undefined,
currentTime: undefined,
canplay: false,
error: false,
};
}
getState(): Observable < RecordingStreamState > {
return this.stateChange.asObservable();
}
playStream(url): Observable < any > {
return this.streamObservable(url).pipe(takeUntil(this.stop$));
}
play(): void {
this.audioObj.play();
}
pause(): void {
this.audioObj.pause();
}
stop(): void {
this.stop$.next();
}
seekTo(seconds): void {
this.audioObj.currentTime = seconds;
}
formatTime(time: number, format: string = 'HH:mm:ss'): string {
const momentTime = time * 1000;
return moment.utc(momentTime).format(format);
}
/**
* Constructor
*
* #param {HttpClient} _httpClient
*/
constructor(
private _httpClient: HttpClient,
) {
// Set the defaults
this.onRecordingClick = new BehaviorSubject([]);
}
}
Looking at your code I can think of a probable solution. I don't know how the Recording object is defined, but if it contains some id it might work. Or you can use some other identifier.
As I said in the comment, state property is shared by all entries within your table. So it's not enough to determine the current playing record. Once it's true for one it's true for all of them. But maybe this can help:
<!-- audio display -->
<ng-container matColumnDef="isPlaying">
<mat-header-cell *matHeaderCellDef>Playing</mat-header-cell>
<mat-cell *matCellDef="let rowRecording">
<button mat-button (click)="playToggle(rowRecording)" [disabled]="state?.error" *ngIf="!state?.playing">
<mat-icon mat-list-icon>play_arrow</mat-icon>
</button>
<button mat-button (click)="pause()" *ngIf="state?.playing && rowRecording.id === recording.id">
<mat-icon mat-list-icon>pause</mat-icon>
</button>
</mat-cell>
</ng-container>
As you can see, I renamed the recording within HTML to rowRecording to differentiate it from the one from the .ts code. Then I'm checking if the state is playing but also if the rowRecording.id equals the ID of assigned recording within .ts. You do it in the playToggle function.
But I would recommend extending the RecordingStreamState object with PlayingRecordId property which would be assigned when you press play. Then you can do someting like this (using your version of HTML)
<button
mat-button
(click)="pause()"
*ngIf="state?.playing && state?.playingRecordId === recording.id"
>

Syncfusion NumericTextbox disable select

I am using an Angular NumericTextbox from Syncfusion in my application. We ran in the issue that when you click on the input it will automaticly select it. Is there a way to disable it?
Issue:
https://gyazo.com/a72bd4aaf4ebda7a98256d31e3959a48
Docs:
https://ej2.syncfusion.com/angular/documentation/numerictextbox/getting-started/
HTML:
<ejs-numerictextbox
[floatLabelType]="floatLabelType"
[enabled]="enabled"
[min]="min"
[max]="max"
[placeholder]="caption"
[format]="format"
[ngClass]="{
'e-success': (control?.dirty || control?.touched) && !control?.invalid,
'e-error': (control?.dirty || control?.touched) && control?.invalid,
'hum-show-required': !this.hideRequired,
'hum-required': isRequired()
}"
[currency]="currency"
(change)="updateControlValue($event)"
(blur)="handleBlur($event)"
></ejs-numerictextbox>
TS
export class FormNumberComponent extends FormBaseComponent {
#ViewChild(NumericTextBoxComponent, { static: true }) valueAccessor: ControlValueAccessor;
#Input() format: string = 'n0';
#Input() min = 0;
#Input() max: number;
#Input() currency = 'EUR';
private busy: boolean;
constructor(injector: Injector, stateService: StateService) {
super(injector);
this.initLogging(false, 'FormNumberComponent');
this.currency = stateService.getCurrency();
}
updateControlValue(event: any): void {
console.log(event);
setTimeout(() => {
// todo - hacky way to fix the issue (integration of ejs with form needs to be refactored)
const formControl: NumericTextBoxComponent = this.valueAccessor as NumericTextBoxComponent;
if (!isObjectEmpty(formControl) && !formControl.isDestroyed) {
this.busy = true;
formControl.focusIn();
formControl.focusOut();
this.busy = false;
}
});
}
handleBlur(e) {
if (!this.busy) {
super.handleBlur(e);
}
}
}
Your requirement to disable the auto select functionality of the Numeric textbox inputs can be achieved by using the click event. please check the code below,
Code snippet
<ejs-numerictextbox
value="10"
(click)="OnClick($event)">
</ejs-numerictextbox>
OnClick(args): void {
var position = args.srcElement.selectionEnd;
args.srcElement.selectionStart = args.srcElement.selectionEnd = position;
}
Sample: https://stackblitz.com/edit/angular-vgqmzs-i93zpr?file=app.component.ts

how to update changes on view in Angular

I have a charts that have a few options for user and I already implemented everything but not sure why I don't see any immediate changes when I click Delete Chart, Publish Chart or Unpublished Chart button. I can only see the result only after I refresh the browser.
I'm new to Angular so I'm wonder how to remove the selected chart immediately or make it disappear when delete button is click and also the same for publish and unpublish chart without having to refresh the browser. any help or suggestion will be really appreciated
#Input() chart: Chart;
data: ChartData;
chartData: ChartData;
hasError: boolean = false;
maxisChartConfig: ChartConfig;
hasChart: boolean = false;
#Input() editMode: boolean;
isTextChart: boolean = false;
constructor(private chartService: ChartService, private router: Router, private dialog: MatDialog) { }
isGrid: boolean = false;
#Input() wsType?: WorkspaceType;
isPublicWs: boolean = false;
ngOnInit(): void {
if(this.wsType) {
if(this.wsType == WorkspaceType.public) {
this.isPublicWs = true;
}
}
this.generateChartConfig();
if(this.chart.chartType == ChartType.text){
this.isTextChart = true;
}
else if(this.chart.chartType == ChartType.grid){
this.isGrid = true;
}
if (this.chart.data) {
if(!this.isTextChart){
this.hasChart = true;
}
this.chartData = this.chart.data;
}
}
deleteChart() {
this.chartService.deleteChart(this.chart.guid).subscribe((deleted) => {
console.log(deleted);
});
}
publishChart() {
this.chartService.setChartPublished(this.chart.guid, !this.chart.isPublished).subscribe((published) => {
console.log(published);
});
}
<button mat-menu-item (click) = "deleteChart()" *ngIf = "chart.hasAccess && chart.canEdit && !chart.isPublished">Delete Chart</button>
<button mat-menu-item (click) = "publishChart()" *ngIf = "chart.canEdit && chart.hasAccess && !chart.isPublished && isPublicWs">Publish Chart</button>
<button mat-menu-item (click) = "publishChart()" *ngIf = "chart.canEdit && chart.hasAccess && chart.isPublished && isPublicWs">Unpublish Chart</button>
The will not run but I uploaded the full code for this component here https://stackblitz.com/edit/angular-ivy-bepxss . Thanks
After each function you can call oninit to reconstruct the charts after changes like this -
deleteChart() {
this.chartService.deleteChart(this.chart.guid).subscribe((deleted) => {
console.log(deleted);
this.ngOnInit(); // Add this line
});
}
///This is how i have refreshed variables in my case -
saveWTPModel(){
if(some condition){
//Perform Save logic
var headers = new HttpHeaders();
headers.append('Content-Type', 'application/json');
const httpOptions = { headers: headers };
this.httpClient.post(environment.api_url + "/User/SavePriority",
this.finalWTPArray, httpOptions)
.subscribe(
response => {
if(response){
this.alertService.success('Priorities Saved.');
//Once i have saved everything I am again calling the api to get the updated data from backend. This function again is called to get the updated Priorities.
this.getWorkTypesPriority(this.loggedinUserId);
}
else{
this.alertService.warning('Problem Occurred.');
}
});
}

Angular 6 : Not able to fetch individual data from different component's JSON object

Scenario:
In Component1, I have a table, I am sending single row's data as a JSON object to Component2's object
Expected result:
I should be able to fetch data using object2, eg. object2.id = id1, object2.title = title1
Actual result: I am getting undefined for values in object2, object2.id= undefined , object2.title = undefined
What I tried:
In Component1 I used JSON.stringify(obj) and in Component2 I was using JSON.parse(obj) to get the object values, but I was getting [obj obj] on alert the JSON object.
I got confused as to how did JSON automatically got converted to Obj without using any JSON.parse.
Good news is, data is being passed to object2, when I alert object2 I get the whole object string with all values.
but when I try to populate single value it gives me undefined msg inspite of the values being present
Any idea how else i can check why it is not working ?
Not sure what exactly I am missing, I am searching since past couple of days, did not find any solution on this or any other site.
Any help is appreciated. Thanks.
Here is my code:
Component1
#Component({
selector: 'myjds',
templateUrl: './myjds.component.html',
styleUrls: ['./myjds.component.scss'],
providers: [DatePipe]
})
#NgModule({
imports: [
ThemeModule,
NgxEchartsModule, Ng2SmartTableModule,
NgxChartsModule, ChartModule, NgxSpinnerModule
],
declarations: [
DashboardComponent,
StatusCardComponent,
ContactsComponent,
EchartsPieComponent,
EchartsBarComponent,
],
entryComponents: []
})
export class MyjdsComponent implements OnInit {
config: ToasterConfig;
private message = null;
position = 'toast-top-right';
animationType = 'flyLeft';
title = 'Result';
content = `I'm cool toaster!`;
timeout = 5000;
toastsLimit = 5;
type = 'info';
isNewestOnTop = true;
isHideOnClick = true;
isDuplicatesPrevented = false;
isCloseButton = true;
EntityID;
LoginUserId;
jdData: JobDescription[] = [];
indJobDescription = {} as JobDescription;
source: LocalDataSource = new LocalDataSource();
serachResults = [];
public nijobmobile;
public nijobcontactemail;
constructor(
private ServiceObj: ApiService,
private spinner: NgxSpinnerService,
private modalService: NgbModal,
private toasterService: ToasterService,
private activeModal: NgbActiveModal,
private datePipe: DatePipe) {
this.EntityID = localStorage.getItem("Entity");
this.LoginUserId = localStorage.getItem("LoginID");
}
private showToast(type: string, title: string, body: string) {
this.config = new ToasterConfig({
positionClass: this.position,
timeout: this.timeout,
newestOnTop: this.isNewestOnTop,
tapToDismiss: this.isHideOnClick,
preventDuplicates: this.isDuplicatesPrevented,
animation: this.animationType,
limit: this.toastsLimit,
});
const toast: Toast = {
type: type,
title: title,
body: body,
timeout: this.timeout,
showCloseButton: this.isCloseButton,
bodyOutputType: BodyOutputType.TrustedHtml,
};
this.toasterService.popAsync(toast);
}
ngOnInit() {
this.loadJobDescription();
}
loadJobDescription(jdData?) {
if (jdData == null || jdData == undefined || jdData == 0) {
alert("data null e ");
this.spinner.show();
let body = JSON.stringify({
nispname: "nijobdescriptionsearch_sp",
ptype: "alljobdescription",
pnijobdescriptionid: 0,
pniuserid: Number(this.LoginUserId),
pnicompid: this.EntityID
});
alert("body string value : " + body);
this.ServiceObj.apicall(body).subscribe(
res => {
this.spinner.hide();
let data: any = res;
if (data.results.Table.length > 0) {
alert("table returns values:" + data.results.Table.length);
this.jdData = data.results.Table;
localStorage.setItem('Message', JSON.stringify(this.jdData));
this.source.load(this.jdData);
}
},
(err) => {
this.spinner.hide();
}
);
}
else {
alert("data ahe baba");
let loginUserId = localStorage.getItem("LoginID");
alert("loginUserId: " + loginUserId);
this.spinner.show();
let body = JSON.stringify({
nispname: "nijobdescriptionsearch_sp",
ptype: "individualJD",
pnijobdescriptionid: jdData.nijobdescriptionid,
pniuserid: Number(this.LoginUserId),
pnicompid: this.EntityID
});
alert("body stringify:" + body);
this.ServiceObj.apicall(body).subscribe(
res => {
this.spinner.hide();
let data: any = res;
if (data.results.Table.length > 0) {
alert("data length" + data.results.Table.length);
this.indJobDescription = data.results.Table;
localStorage.setItem('Message1', JSON.stringify(this.indJobDescription));
// alert("result of indjobdescription: " + JSON.stringify(this.indJobDescription));
const activeModal = this.modalService.open(IndJobDescriptionComponent, {
size: 'lg',
backdrop: 'static',
container: 'nb-layout',
});
}
},
(err) => {
this.spinner.hide();
}
);
}
}
}
Component2
selector: 'commentresult',
templateUrl: './indjobdescription.component.html',
styleUrls: ['./indjobdescription.component.scss']
})
export class IndJobDescriptionComponent implements OnInit {
private msg: string = '';
private msg1: string = "";
public dialog: any;
public dialog1 :any;
public existingstaffid = [];
errorMsgRolename: string = '';
errorMsgRoledescription: string = '';
isValidRolename: boolean = true;
isValidRoledescription: boolean = true;
public ShlocationAutoComplete;
public ShroleAutoComplete;
public ShskillAutoComplete;
public ShdomainAutoComplete;
public ShcertAutocomplete;
public alldata;
public nijobmobile;
public nijobcontactemail;
pager: any = {};
pagedItems: any[];
jdData: JobDescription[] = [];
indJobDescription = {} as JobDescription;
LoginUserId = localStorage.getItem("LoginID");
source: LocalDataSource = new LocalDataSource();
constructor(private modalService: NgbModal,
private spinner: NgxSpinnerService,
private _sanitizer: DomSanitizer,
private data: DataService,
private activeModal: NgbActiveModal,
private ServiceObj: ApiService,
private pagerService: PagerService,
private toasterService: ToasterService) {
this.EntityID = localStorage.getItem("Entity");
}
profile: any;
private EntityID: string;
private message = null;
config: ToasterConfig;
position = 'toast-top-right';
animationType = 'flyLeft';
title = 'Result';
content = `I'm cool toaster!`;
timeout = 5000;
toastsLimit = 5;
type = 'info';
isNewestOnTop = true;
isHideOnClick = true;
isDuplicatesPrevented = false;
isCloseButton = true;
ngOnInit() {
this.msg1 = localStorage.getItem("Message1");
//this.indJobDescription = JSON.parse(this.msg1); //on doing alert, this line is returning [obj obj]
alert("user id: " + this.indJobDescription.nijobcreateuserid);
}
closeModal() {
this.activeModal.close();
}
private showToast(type: string, title: string, body: string) {
this.config = new ToasterConfig({
positionClass: this.position,
timeout: this.timeout,
newestOnTop: this.isNewestOnTop,
tapToDismiss: this.isHideOnClick,
preventDuplicates: this.isDuplicatesPrevented,
animation: this.animationType,
limit: this.toastsLimit,
});
const toast: Toast = {
type: type,
title: title,
body: body,
timeout: this.timeout,
showCloseButton: this.isCloseButton,
bodyOutputType: BodyOutputType.TrustedHtml,
};
this.toasterService.popAsync(toast);
}
SaveData() {
let t = window.location.host;
let tvpselectiondtl: tvp_selectiondtl[] = [];
let LoginUserId = localStorage.getItem("LoginID");
}
}
PFB screenshot of the JSON string, sorry console.log is not working so had to take screen shot of the alert,
As I can see in json you are storing an array of objects .
this.msg1 = localStorage.getItem("Message1");
this.indJobDescription = JSON.parse(this.msg1); //on doing alert, this line is
returning [obj obj]
alert("user id: " + this.indJobDescription[0].nijobcreateuserid); //It is array
If there is multiple entry of indJobDescription then use *ngFor to read each object.
for (let i = 0; i < this.indJobDescription.length ; i++) {
var jobCreateUserId= this.indJobDescription[i].nijobcreateuserid;
..........
}
and it will solve your issue.
keep this simple
var product=[{"sno":"1","description":"test"}] =Array of object ==>product[0].sno
var product={"sno":"1","description":"test"} = it presents object. ==> product.sno
There are two main ways to share data between components, input and output properties and shared services.
If component 2 is a child of component 1 then use inputs
<component2 [data]="propertyOfComponent1"></component2>
and in component 2 decorate the data property as an input
#Input() data;
After the component has initalised data will be the data passed from component 1. You can access it in the ngOnInit method but not the constructor as it wont be wired up just yet.
If they are not in a parent child relationship use a shared service that is dependency injected into both components constructor.
constructor(private sharedService: SharedService) {
}
and both components will get the same instance of the service.
#Injectable()
export class SharedService {
data = new SomeObject();
}