forked from CIT/Vmeda.Online
		
	MOBILE-3565 components: Implement loading component
This commit is contained in:
		
							parent
							
								
									072c05c268
								
							
						
					
					
						commit
						a6bf6afe7a
					
				| @ -13,18 +13,24 @@ | |||||||
| // limitations under the License.
 | // limitations under the License.
 | ||||||
| 
 | 
 | ||||||
| import { NgModule } from '@angular/core'; | import { NgModule } from '@angular/core'; | ||||||
|  | import { IonicModule } from '@ionic/angular'; | ||||||
| 
 | 
 | ||||||
| import { CoreIconComponent } from './icon/icon'; | import { CoreIconComponent } from './icon/icon'; | ||||||
|  | import { CoreLoadingComponent } from './loading/loading'; | ||||||
| import { CoreShowPasswordComponent } from './show-password/show-password'; | import { CoreShowPasswordComponent } from './show-password/show-password'; | ||||||
| 
 | 
 | ||||||
| @NgModule({ | @NgModule({ | ||||||
|     declarations: [ |     declarations: [ | ||||||
|         CoreIconComponent, |         CoreIconComponent, | ||||||
|  |         CoreLoadingComponent, | ||||||
|         CoreShowPasswordComponent, |         CoreShowPasswordComponent, | ||||||
|     ], |     ], | ||||||
|     imports: [], |     imports: [ | ||||||
|  |         IonicModule, | ||||||
|  |     ], | ||||||
|     exports: [ |     exports: [ | ||||||
|         CoreIconComponent, |         CoreIconComponent, | ||||||
|  |         CoreLoadingComponent, | ||||||
|         CoreShowPasswordComponent, |         CoreShowPasswordComponent, | ||||||
|     ], |     ], | ||||||
| }) | }) | ||||||
|  | |||||||
							
								
								
									
										10
									
								
								src/app/components/loading/core-loading.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/app/components/loading/core-loading.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | <div class="core-loading-container" *ngIf="!hideUntil" role="status"> <!-- @todo [@coreShowHideAnimation]  --> | ||||||
|  |     <span class="core-loading-spinner"> | ||||||
|  |         <ion-spinner></ion-spinner> | ||||||
|  |         <p class="core-loading-message" *ngIf="message" role="status">{{message}}</p> | ||||||
|  |     </span> | ||||||
|  | </div> | ||||||
|  | <div #content class="core-loading-content" [id]="uniqueId" [attr.aria-busy]="hideUntil"> | ||||||
|  |     <ng-content *ngIf="hideUntil"> | ||||||
|  |     </ng-content> <!-- @todo [@coreShowHideAnimation]  --> | ||||||
|  | </div> | ||||||
							
								
								
									
										67
									
								
								src/app/components/loading/loading.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/app/components/loading/loading.scss
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,67 @@ | |||||||
|  | ion-app.app-root { | ||||||
|  |     core-loading { | ||||||
|  |         // @todo @include core-transition(height, 200ms); | ||||||
|  | 
 | ||||||
|  |         .core-loading-container { | ||||||
|  |             width: 100%; | ||||||
|  |             text-align: center; | ||||||
|  |             padding-top: 10px; | ||||||
|  |             clear: both; | ||||||
|  |             /* @todo @include darkmode() { | ||||||
|  |                 color: $core-dark-text-color; | ||||||
|  |             } */ | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         .core-loading-content { | ||||||
|  |             display: inline; | ||||||
|  |             padding-bottom: 1px; /* This makes height be real */ | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         &.core-loading-noheight .core-loading-content { | ||||||
|  |             height: auto; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         &.safe-area-page { | ||||||
|  |             padding-left: 0 !important; | ||||||
|  |             padding-right: 0 !important; | ||||||
|  | 
 | ||||||
|  |             > .core-loading-content > *:not[padding], | ||||||
|  |             > .core-loading-content-loading > *:not[padding] { | ||||||
|  |                 // @todo @include safe-area-padding-horizontal(0px, 0px); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     .scroll-content > core-loading, | ||||||
|  |     ion-content > .scroll-content > core-loading, | ||||||
|  |     core-tab core-loading, | ||||||
|  |     .core-loading-center { | ||||||
|  |         position: static !important; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     .scroll-content > core-loading, | ||||||
|  |     ion-content > .scroll-content > core-loading, | ||||||
|  |     core-tab core-loading, | ||||||
|  |     .core-loading-center, | ||||||
|  |     core-loading.core-loading-loaded { | ||||||
|  |         position: relative; | ||||||
|  | 
 | ||||||
|  |         > .core-loading-container { | ||||||
|  |             position: absolute; | ||||||
|  |             // @todo @include position(0, 0, 0, 0); | ||||||
|  |             display: table; | ||||||
|  |             height: 100%; | ||||||
|  |             width: 100%; | ||||||
|  |             z-index: 1; | ||||||
|  |             margin: 0; | ||||||
|  |             padding: 0; | ||||||
|  |             clear: both; | ||||||
|  | 
 | ||||||
|  |             .core-loading-spinner { | ||||||
|  |                 display: table-cell; | ||||||
|  |                 text-align: center; | ||||||
|  |                 vertical-align: middle; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										120
									
								
								src/app/components/loading/loading.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								src/app/components/loading/loading.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,120 @@ | |||||||
|  | // (C) Copyright 2015 Moodle Pty Ltd.
 | ||||||
|  | //
 | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||||
|  | // you may not use this file except in compliance with the License.
 | ||||||
|  | // You may obtain a copy of the License at
 | ||||||
|  | //
 | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | //
 | ||||||
|  | // Unless required by applicable law or agreed to in writing, software
 | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||||
|  | // See the License for the specific language governing permissions and
 | ||||||
|  | // limitations under the License.
 | ||||||
|  | 
 | ||||||
|  | import { Component, Input, OnInit, OnChanges, SimpleChange, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; | ||||||
|  | 
 | ||||||
|  | import { CoreEvents, CoreEventsProvider } from '@services/events'; | ||||||
|  | import { CoreUtils } from '@services/utils/utils'; | ||||||
|  | import { Translate } from '@singletons/core.singletons'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Component to show a loading spinner and message while data is being loaded. | ||||||
|  |  * | ||||||
|  |  * It will show a spinner with a message and hide all the content until 'hideUntil' variable is set to a truthy value (!!hideUntil). | ||||||
|  |  * If 'message' isn't set, default message "Loading" is shown. | ||||||
|  |  * 'message' attribute accepts hardcoded strings, variables, filters, etc. E.g. [message]="'core.loading' | translate". | ||||||
|  |  * | ||||||
|  |  * Usage: | ||||||
|  |  * <core-loading [message]="loadingMessage" [hideUntil]="dataLoaded"> | ||||||
|  |  *     <!-- CONTENT TO HIDE UNTIL LOADED --> | ||||||
|  |  * </core-loading> | ||||||
|  |  * | ||||||
|  |  * IMPORTANT: Due to how ng-content works in Angular, the content of core-loading will be executed as soon as your view | ||||||
|  |  * is loaded, even if the content hidden. So if you have the following code: | ||||||
|  |  * <core-loading [hideUntil]="dataLoaded"><my-component></my-component></core-loading> | ||||||
|  |  * | ||||||
|  |  * The component "my-component" will be initialized immediately, even if dataLoaded is false, but it will be hidden. If you want | ||||||
|  |  * your component to be initialized only if dataLoaded is true, then you should use ngIf: | ||||||
|  |  * <core-loading [hideUntil]="dataLoaded"><my-component *ngIf="dataLoaded"></my-component></core-loading> | ||||||
|  |  */ | ||||||
|  | @Component({ | ||||||
|  |     selector: 'core-loading', | ||||||
|  |     templateUrl: 'core-loading.html', | ||||||
|  |     styleUrls: ['loading.scss'], | ||||||
|  |     // @todo animations: [coreShowHideAnimation],
 | ||||||
|  | }) | ||||||
|  | export class CoreLoadingComponent implements OnInit, OnChanges, AfterViewInit { | ||||||
|  | 
 | ||||||
|  |     @Input() hideUntil: unknown; // Determine when should the contents be shown.
 | ||||||
|  |     @Input() message?: string; // Message to show while loading.
 | ||||||
|  |     @ViewChild('content') content: ElementRef; | ||||||
|  | 
 | ||||||
|  |     protected uniqueId: string; | ||||||
|  |     protected element: HTMLElement; // Current element.
 | ||||||
|  | 
 | ||||||
|  |     constructor(element: ElementRef) { | ||||||
|  |         this.element = element.nativeElement; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Component being initialized. | ||||||
|  |      */ | ||||||
|  |     ngOnInit(): void { | ||||||
|  |         // Calculate the unique ID.
 | ||||||
|  |         this.uniqueId = 'core-loading-content-' + CoreUtils.instance.getUniqueId('CoreLoadingComponent'); | ||||||
|  | 
 | ||||||
|  |         if (!this.message) { | ||||||
|  |             // Default loading message.
 | ||||||
|  |             this.message = Translate.instance.instant('core.loading'); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * View has been initialized. | ||||||
|  |      */ | ||||||
|  |     ngAfterViewInit(): void { | ||||||
|  |         // Add class if loaded on init.
 | ||||||
|  |         if (this.hideUntil) { | ||||||
|  |             this.element.classList.add('core-loading-loaded'); | ||||||
|  |             this.content?.nativeElement.classList.add('core-loading-content'); | ||||||
|  |         } else { | ||||||
|  |             this.content?.nativeElement.classList.remove('core-loading-content'); | ||||||
|  |             this.content?.nativeElement.classList.add('core-loading-content-loading'); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Component input changed. | ||||||
|  |      * | ||||||
|  |      * @param changes Changes. | ||||||
|  |      */ | ||||||
|  |     ngOnChanges(changes: { [name: string]: SimpleChange }): void { | ||||||
|  |         if (changes.hideUntil) { | ||||||
|  |             if (this.hideUntil) { | ||||||
|  |                 setTimeout(() => { | ||||||
|  |                     // Content is loaded so, center the spinner on the content itself.
 | ||||||
|  |                     this.element.classList.add('core-loading-loaded'); | ||||||
|  |                     setTimeout(() => { | ||||||
|  |                         // Change CSS to force calculate height.
 | ||||||
|  |                         this.content?.nativeElement.classList.add('core-loading-content'); | ||||||
|  |                         this.content?.nativeElement.classList.remove('core-loading-content-loading'); | ||||||
|  |                     }, 500); | ||||||
|  |                 }); | ||||||
|  |             } else { | ||||||
|  |                 this.element.classList.remove('core-loading-loaded'); | ||||||
|  |                 this.content?.nativeElement.classList.remove('core-loading-content'); | ||||||
|  |                 this.content?.nativeElement.classList.add('core-loading-content-loading'); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Trigger the event after a timeout since the elements inside ngIf haven't been added to DOM yet.
 | ||||||
|  |             setTimeout(() => { | ||||||
|  |                 CoreEvents.instance.trigger(CoreEventsProvider.CORE_LOADING_CHANGED, { | ||||||
|  |                     loaded: !!this.hideUntil, | ||||||
|  |                     uniqueId: this.uniqueId, | ||||||
|  |                 }); | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user