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.
 | ||||
| 
 | ||||
| import { NgModule } from '@angular/core'; | ||||
| import { IonicModule } from '@ionic/angular'; | ||||
| 
 | ||||
| import { CoreIconComponent } from './icon/icon'; | ||||
| import { CoreLoadingComponent } from './loading/loading'; | ||||
| import { CoreShowPasswordComponent } from './show-password/show-password'; | ||||
| 
 | ||||
| @NgModule({ | ||||
|     declarations: [ | ||||
|         CoreIconComponent, | ||||
|         CoreLoadingComponent, | ||||
|         CoreShowPasswordComponent, | ||||
|     ], | ||||
|     imports: [], | ||||
|     imports: [ | ||||
|         IonicModule, | ||||
|     ], | ||||
|     exports: [ | ||||
|         CoreIconComponent, | ||||
|         CoreLoadingComponent, | ||||
|         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