Showing the loading spinner icon on all components
I have written the code to show the loading spinner on all components when any event is triggered. It works fine on a single component but the issue with it, I have to show the same loading spinner on the around multiple components when certain event is triggered. See below code:
tasks()
this.handler.activateLoader();
this.tasksService.get(this.page, this.pageSize).subscribe(results =>
this.handler.hideLoader();
if (this.handler.handle(results))
return;
this.tasksRes = results['data'];
for (let i = 0; i < this.tasksRes.length; i++)
if (this.tasksRes[i].status == 'In_progress' && this.tasksRes[i].eventType == 'Sync' &&
this.tasksRes[i].entityId == this.id)
this.progressFlag = true;
break;
else
this.progressFlag = false;
this.length = results['totalElements'];
, error =>
this.handler.hideLoader();
this.handler.error(error);
);
connect()
let source = new EventSource('/api/v1/events/register');
source.addEventListener('message', message =>
this.tasks();
);
And on ngOnInit(), I have called these 2 methods as below then its working fine.
ngOnInit()
this.tasks();
this.connect();
The actual requirement is when I run a particular event the button is going to be disabled and at the same time the spinner loading will come. I have achieved this one. But how to show the same spinner on multiple components so that the user can know that the task is running.
This is how I am showing the loading spinner. See below:
<span class="text-warning pull-right" *ngIf="progressFlag">
<i class="fa fa-spinner fa-spin fa-2x"></i>
</span>
In my code, I have many components at around 17-18 where I need to show the loading spinner. If I want to show the spinner globally means I can show it on either header and footer component which is common to my entire template. Can any one provide any ideas on it.
Thanks.
javascript angular typescript
add a comment |
I have written the code to show the loading spinner on all components when any event is triggered. It works fine on a single component but the issue with it, I have to show the same loading spinner on the around multiple components when certain event is triggered. See below code:
tasks()
this.handler.activateLoader();
this.tasksService.get(this.page, this.pageSize).subscribe(results =>
this.handler.hideLoader();
if (this.handler.handle(results))
return;
this.tasksRes = results['data'];
for (let i = 0; i < this.tasksRes.length; i++)
if (this.tasksRes[i].status == 'In_progress' && this.tasksRes[i].eventType == 'Sync' &&
this.tasksRes[i].entityId == this.id)
this.progressFlag = true;
break;
else
this.progressFlag = false;
this.length = results['totalElements'];
, error =>
this.handler.hideLoader();
this.handler.error(error);
);
connect()
let source = new EventSource('/api/v1/events/register');
source.addEventListener('message', message =>
this.tasks();
);
And on ngOnInit(), I have called these 2 methods as below then its working fine.
ngOnInit()
this.tasks();
this.connect();
The actual requirement is when I run a particular event the button is going to be disabled and at the same time the spinner loading will come. I have achieved this one. But how to show the same spinner on multiple components so that the user can know that the task is running.
This is how I am showing the loading spinner. See below:
<span class="text-warning pull-right" *ngIf="progressFlag">
<i class="fa fa-spinner fa-spin fa-2x"></i>
</span>
In my code, I have many components at around 17-18 where I need to show the loading spinner. If I want to show the spinner globally means I can show it on either header and footer component which is common to my entire template. Can any one provide any ideas on it.
Thanks.
javascript angular typescript
add a comment |
I have written the code to show the loading spinner on all components when any event is triggered. It works fine on a single component but the issue with it, I have to show the same loading spinner on the around multiple components when certain event is triggered. See below code:
tasks()
this.handler.activateLoader();
this.tasksService.get(this.page, this.pageSize).subscribe(results =>
this.handler.hideLoader();
if (this.handler.handle(results))
return;
this.tasksRes = results['data'];
for (let i = 0; i < this.tasksRes.length; i++)
if (this.tasksRes[i].status == 'In_progress' && this.tasksRes[i].eventType == 'Sync' &&
this.tasksRes[i].entityId == this.id)
this.progressFlag = true;
break;
else
this.progressFlag = false;
this.length = results['totalElements'];
, error =>
this.handler.hideLoader();
this.handler.error(error);
);
connect()
let source = new EventSource('/api/v1/events/register');
source.addEventListener('message', message =>
this.tasks();
);
And on ngOnInit(), I have called these 2 methods as below then its working fine.
ngOnInit()
this.tasks();
this.connect();
The actual requirement is when I run a particular event the button is going to be disabled and at the same time the spinner loading will come. I have achieved this one. But how to show the same spinner on multiple components so that the user can know that the task is running.
This is how I am showing the loading spinner. See below:
<span class="text-warning pull-right" *ngIf="progressFlag">
<i class="fa fa-spinner fa-spin fa-2x"></i>
</span>
In my code, I have many components at around 17-18 where I need to show the loading spinner. If I want to show the spinner globally means I can show it on either header and footer component which is common to my entire template. Can any one provide any ideas on it.
Thanks.
javascript angular typescript
I have written the code to show the loading spinner on all components when any event is triggered. It works fine on a single component but the issue with it, I have to show the same loading spinner on the around multiple components when certain event is triggered. See below code:
tasks()
this.handler.activateLoader();
this.tasksService.get(this.page, this.pageSize).subscribe(results =>
this.handler.hideLoader();
if (this.handler.handle(results))
return;
this.tasksRes = results['data'];
for (let i = 0; i < this.tasksRes.length; i++)
if (this.tasksRes[i].status == 'In_progress' && this.tasksRes[i].eventType == 'Sync' &&
this.tasksRes[i].entityId == this.id)
this.progressFlag = true;
break;
else
this.progressFlag = false;
this.length = results['totalElements'];
, error =>
this.handler.hideLoader();
this.handler.error(error);
);
connect()
let source = new EventSource('/api/v1/events/register');
source.addEventListener('message', message =>
this.tasks();
);
And on ngOnInit(), I have called these 2 methods as below then its working fine.
ngOnInit()
this.tasks();
this.connect();
The actual requirement is when I run a particular event the button is going to be disabled and at the same time the spinner loading will come. I have achieved this one. But how to show the same spinner on multiple components so that the user can know that the task is running.
This is how I am showing the loading spinner. See below:
<span class="text-warning pull-right" *ngIf="progressFlag">
<i class="fa fa-spinner fa-spin fa-2x"></i>
</span>
In my code, I have many components at around 17-18 where I need to show the loading spinner. If I want to show the spinner globally means I can show it on either header and footer component which is common to my entire template. Can any one provide any ideas on it.
Thanks.
javascript angular typescript
javascript angular typescript
edited Nov 14 '18 at 5:57
Busy Bee
1,0591719
1,0591719
asked Nov 14 '18 at 5:46
youiyoui
339314
339314
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
Please search keyword HttpInterceptor learn details. One simple example below:
// siteHttpInterceptor.ts
import Injectable from '@angular/core';
import HttpRequest, HttpInterceptor, HttpHandler, HttpEvent, HttpResponse from '@angular/common/http';
import throwError from 'rxjs';
import tap, catchError from 'rxjs/operators';
import LoadingService from './loading.service';
@Injectable()
export class SiteHttpInterceptor implements HttpInterceptor
constructor(private loadingService: LoadingService)
intercept(request: HttpRequest<any>, httpHandler: HttpHandler): Observable<any>
/* Start loading here */
this.loadingService.startLoading();
return httpHandler.handle(request).pipe(
tap((event: HttpEvent<any>) =>
/* End loading */
this.loadingService.endLoading();
,
(err: any) =>
/* End loading */
this.loadingService.endLoading();
),
catchError(err =>
return throwError(err);
)
);
//loading.service.ts LoadingService base on Ionic framework, you can instead it
import Injectable from '@angular/core';
import LoadingController from '@ionic/angular';
@Injectable(
providedIn: 'root'
)
export class LoadingService
private loaders = ;
//sometimes, the request so quickly then close event earlier than open loading bar
private badLoaders = 0;
constructor(
private loadingController: LoadingController
)
async startLoading()
if (this.badLoaders > 0)
this.badLoaders --;
else
await this.loadingController.create(
message: 'Loading ...',
).then(loader =>
this.loaders.push(loader);
loader.present().then(() =>
//if it is bad loader, close
if (this.badLoaders > 0)
this.badLoaders --;
this.endLoading();
);
);
endLoading()
let loader = this.loaders.pop();
if (loader)
loader.dismiss();
else
// it is mean close event earlier
this.badLoaders ++;
Use it then you not need manage loader handle each request method.
Loader doesn't always work only for HTTP request - be generic with your answer
– Rahul
Nov 14 '18 at 6:31
@RahulSwamynathan of course, you can build one service and define one subject there, same time subscribe it in your loader, and at other component, call service.subject.next('open'/'close').
– Nick Wang
Nov 14 '18 at 8:24
add a comment |
Put your spinner at the main component.. in most cases its the AppComponent
Then put a these on your shared service
private LoadingStatus = new Subject<boolean>();
// Observable string streams
IsLoading$ = this.LoadingStatus.asObservable();
// Service message commands
triggerLoading(status: boolean)
this.LoadingStatus.next(mission);
Then at your sender component call triggerLoading(true)
or triggerLoading(false)
from the service and subscribe at your main component (AppComponent):
this.shareService.IsLoading$.subscribe( data => progressFlag = data )
Or Add your logic as this:
this.shareService.IsLoading$.subscribe(
data =>
if(data)
// start loading logic here
else
// end loading logic here
)
Source: Angular - Component Interaction
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53293874%2fshowing-the-loading-spinner-icon-on-all-components%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Please search keyword HttpInterceptor learn details. One simple example below:
// siteHttpInterceptor.ts
import Injectable from '@angular/core';
import HttpRequest, HttpInterceptor, HttpHandler, HttpEvent, HttpResponse from '@angular/common/http';
import throwError from 'rxjs';
import tap, catchError from 'rxjs/operators';
import LoadingService from './loading.service';
@Injectable()
export class SiteHttpInterceptor implements HttpInterceptor
constructor(private loadingService: LoadingService)
intercept(request: HttpRequest<any>, httpHandler: HttpHandler): Observable<any>
/* Start loading here */
this.loadingService.startLoading();
return httpHandler.handle(request).pipe(
tap((event: HttpEvent<any>) =>
/* End loading */
this.loadingService.endLoading();
,
(err: any) =>
/* End loading */
this.loadingService.endLoading();
),
catchError(err =>
return throwError(err);
)
);
//loading.service.ts LoadingService base on Ionic framework, you can instead it
import Injectable from '@angular/core';
import LoadingController from '@ionic/angular';
@Injectable(
providedIn: 'root'
)
export class LoadingService
private loaders = ;
//sometimes, the request so quickly then close event earlier than open loading bar
private badLoaders = 0;
constructor(
private loadingController: LoadingController
)
async startLoading()
if (this.badLoaders > 0)
this.badLoaders --;
else
await this.loadingController.create(
message: 'Loading ...',
).then(loader =>
this.loaders.push(loader);
loader.present().then(() =>
//if it is bad loader, close
if (this.badLoaders > 0)
this.badLoaders --;
this.endLoading();
);
);
endLoading()
let loader = this.loaders.pop();
if (loader)
loader.dismiss();
else
// it is mean close event earlier
this.badLoaders ++;
Use it then you not need manage loader handle each request method.
Loader doesn't always work only for HTTP request - be generic with your answer
– Rahul
Nov 14 '18 at 6:31
@RahulSwamynathan of course, you can build one service and define one subject there, same time subscribe it in your loader, and at other component, call service.subject.next('open'/'close').
– Nick Wang
Nov 14 '18 at 8:24
add a comment |
Please search keyword HttpInterceptor learn details. One simple example below:
// siteHttpInterceptor.ts
import Injectable from '@angular/core';
import HttpRequest, HttpInterceptor, HttpHandler, HttpEvent, HttpResponse from '@angular/common/http';
import throwError from 'rxjs';
import tap, catchError from 'rxjs/operators';
import LoadingService from './loading.service';
@Injectable()
export class SiteHttpInterceptor implements HttpInterceptor
constructor(private loadingService: LoadingService)
intercept(request: HttpRequest<any>, httpHandler: HttpHandler): Observable<any>
/* Start loading here */
this.loadingService.startLoading();
return httpHandler.handle(request).pipe(
tap((event: HttpEvent<any>) =>
/* End loading */
this.loadingService.endLoading();
,
(err: any) =>
/* End loading */
this.loadingService.endLoading();
),
catchError(err =>
return throwError(err);
)
);
//loading.service.ts LoadingService base on Ionic framework, you can instead it
import Injectable from '@angular/core';
import LoadingController from '@ionic/angular';
@Injectable(
providedIn: 'root'
)
export class LoadingService
private loaders = ;
//sometimes, the request so quickly then close event earlier than open loading bar
private badLoaders = 0;
constructor(
private loadingController: LoadingController
)
async startLoading()
if (this.badLoaders > 0)
this.badLoaders --;
else
await this.loadingController.create(
message: 'Loading ...',
).then(loader =>
this.loaders.push(loader);
loader.present().then(() =>
//if it is bad loader, close
if (this.badLoaders > 0)
this.badLoaders --;
this.endLoading();
);
);
endLoading()
let loader = this.loaders.pop();
if (loader)
loader.dismiss();
else
// it is mean close event earlier
this.badLoaders ++;
Use it then you not need manage loader handle each request method.
Loader doesn't always work only for HTTP request - be generic with your answer
– Rahul
Nov 14 '18 at 6:31
@RahulSwamynathan of course, you can build one service and define one subject there, same time subscribe it in your loader, and at other component, call service.subject.next('open'/'close').
– Nick Wang
Nov 14 '18 at 8:24
add a comment |
Please search keyword HttpInterceptor learn details. One simple example below:
// siteHttpInterceptor.ts
import Injectable from '@angular/core';
import HttpRequest, HttpInterceptor, HttpHandler, HttpEvent, HttpResponse from '@angular/common/http';
import throwError from 'rxjs';
import tap, catchError from 'rxjs/operators';
import LoadingService from './loading.service';
@Injectable()
export class SiteHttpInterceptor implements HttpInterceptor
constructor(private loadingService: LoadingService)
intercept(request: HttpRequest<any>, httpHandler: HttpHandler): Observable<any>
/* Start loading here */
this.loadingService.startLoading();
return httpHandler.handle(request).pipe(
tap((event: HttpEvent<any>) =>
/* End loading */
this.loadingService.endLoading();
,
(err: any) =>
/* End loading */
this.loadingService.endLoading();
),
catchError(err =>
return throwError(err);
)
);
//loading.service.ts LoadingService base on Ionic framework, you can instead it
import Injectable from '@angular/core';
import LoadingController from '@ionic/angular';
@Injectable(
providedIn: 'root'
)
export class LoadingService
private loaders = ;
//sometimes, the request so quickly then close event earlier than open loading bar
private badLoaders = 0;
constructor(
private loadingController: LoadingController
)
async startLoading()
if (this.badLoaders > 0)
this.badLoaders --;
else
await this.loadingController.create(
message: 'Loading ...',
).then(loader =>
this.loaders.push(loader);
loader.present().then(() =>
//if it is bad loader, close
if (this.badLoaders > 0)
this.badLoaders --;
this.endLoading();
);
);
endLoading()
let loader = this.loaders.pop();
if (loader)
loader.dismiss();
else
// it is mean close event earlier
this.badLoaders ++;
Use it then you not need manage loader handle each request method.
Please search keyword HttpInterceptor learn details. One simple example below:
// siteHttpInterceptor.ts
import Injectable from '@angular/core';
import HttpRequest, HttpInterceptor, HttpHandler, HttpEvent, HttpResponse from '@angular/common/http';
import throwError from 'rxjs';
import tap, catchError from 'rxjs/operators';
import LoadingService from './loading.service';
@Injectable()
export class SiteHttpInterceptor implements HttpInterceptor
constructor(private loadingService: LoadingService)
intercept(request: HttpRequest<any>, httpHandler: HttpHandler): Observable<any>
/* Start loading here */
this.loadingService.startLoading();
return httpHandler.handle(request).pipe(
tap((event: HttpEvent<any>) =>
/* End loading */
this.loadingService.endLoading();
,
(err: any) =>
/* End loading */
this.loadingService.endLoading();
),
catchError(err =>
return throwError(err);
)
);
//loading.service.ts LoadingService base on Ionic framework, you can instead it
import Injectable from '@angular/core';
import LoadingController from '@ionic/angular';
@Injectable(
providedIn: 'root'
)
export class LoadingService
private loaders = ;
//sometimes, the request so quickly then close event earlier than open loading bar
private badLoaders = 0;
constructor(
private loadingController: LoadingController
)
async startLoading()
if (this.badLoaders > 0)
this.badLoaders --;
else
await this.loadingController.create(
message: 'Loading ...',
).then(loader =>
this.loaders.push(loader);
loader.present().then(() =>
//if it is bad loader, close
if (this.badLoaders > 0)
this.badLoaders --;
this.endLoading();
);
);
endLoading()
let loader = this.loaders.pop();
if (loader)
loader.dismiss();
else
// it is mean close event earlier
this.badLoaders ++;
Use it then you not need manage loader handle each request method.
answered Nov 14 '18 at 6:21
Nick WangNick Wang
54925
54925
Loader doesn't always work only for HTTP request - be generic with your answer
– Rahul
Nov 14 '18 at 6:31
@RahulSwamynathan of course, you can build one service and define one subject there, same time subscribe it in your loader, and at other component, call service.subject.next('open'/'close').
– Nick Wang
Nov 14 '18 at 8:24
add a comment |
Loader doesn't always work only for HTTP request - be generic with your answer
– Rahul
Nov 14 '18 at 6:31
@RahulSwamynathan of course, you can build one service and define one subject there, same time subscribe it in your loader, and at other component, call service.subject.next('open'/'close').
– Nick Wang
Nov 14 '18 at 8:24
Loader doesn't always work only for HTTP request - be generic with your answer
– Rahul
Nov 14 '18 at 6:31
Loader doesn't always work only for HTTP request - be generic with your answer
– Rahul
Nov 14 '18 at 6:31
@RahulSwamynathan of course, you can build one service and define one subject there, same time subscribe it in your loader, and at other component, call service.subject.next('open'/'close').
– Nick Wang
Nov 14 '18 at 8:24
@RahulSwamynathan of course, you can build one service and define one subject there, same time subscribe it in your loader, and at other component, call service.subject.next('open'/'close').
– Nick Wang
Nov 14 '18 at 8:24
add a comment |
Put your spinner at the main component.. in most cases its the AppComponent
Then put a these on your shared service
private LoadingStatus = new Subject<boolean>();
// Observable string streams
IsLoading$ = this.LoadingStatus.asObservable();
// Service message commands
triggerLoading(status: boolean)
this.LoadingStatus.next(mission);
Then at your sender component call triggerLoading(true)
or triggerLoading(false)
from the service and subscribe at your main component (AppComponent):
this.shareService.IsLoading$.subscribe( data => progressFlag = data )
Or Add your logic as this:
this.shareService.IsLoading$.subscribe(
data =>
if(data)
// start loading logic here
else
// end loading logic here
)
Source: Angular - Component Interaction
add a comment |
Put your spinner at the main component.. in most cases its the AppComponent
Then put a these on your shared service
private LoadingStatus = new Subject<boolean>();
// Observable string streams
IsLoading$ = this.LoadingStatus.asObservable();
// Service message commands
triggerLoading(status: boolean)
this.LoadingStatus.next(mission);
Then at your sender component call triggerLoading(true)
or triggerLoading(false)
from the service and subscribe at your main component (AppComponent):
this.shareService.IsLoading$.subscribe( data => progressFlag = data )
Or Add your logic as this:
this.shareService.IsLoading$.subscribe(
data =>
if(data)
// start loading logic here
else
// end loading logic here
)
Source: Angular - Component Interaction
add a comment |
Put your spinner at the main component.. in most cases its the AppComponent
Then put a these on your shared service
private LoadingStatus = new Subject<boolean>();
// Observable string streams
IsLoading$ = this.LoadingStatus.asObservable();
// Service message commands
triggerLoading(status: boolean)
this.LoadingStatus.next(mission);
Then at your sender component call triggerLoading(true)
or triggerLoading(false)
from the service and subscribe at your main component (AppComponent):
this.shareService.IsLoading$.subscribe( data => progressFlag = data )
Or Add your logic as this:
this.shareService.IsLoading$.subscribe(
data =>
if(data)
// start loading logic here
else
// end loading logic here
)
Source: Angular - Component Interaction
Put your spinner at the main component.. in most cases its the AppComponent
Then put a these on your shared service
private LoadingStatus = new Subject<boolean>();
// Observable string streams
IsLoading$ = this.LoadingStatus.asObservable();
// Service message commands
triggerLoading(status: boolean)
this.LoadingStatus.next(mission);
Then at your sender component call triggerLoading(true)
or triggerLoading(false)
from the service and subscribe at your main component (AppComponent):
this.shareService.IsLoading$.subscribe( data => progressFlag = data )
Or Add your logic as this:
this.shareService.IsLoading$.subscribe(
data =>
if(data)
// start loading logic here
else
// end loading logic here
)
Source: Angular - Component Interaction
answered Nov 14 '18 at 6:23
Lowell Ed LlamesLowell Ed Llames
1297
1297
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53293874%2fshowing-the-loading-spinner-icon-on-all-components%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown