forked from EVOgeek/Vmeda.Online
		
	MOBILE-3947 form: Add types to FormControl
This commit is contained in:
		
							parent
							
								
									350f5792ca
								
							
						
					
					
						commit
						27b980d710
					
				| @ -39,10 +39,10 @@ import { CoreLogger } from '@singletons/logger'; | ||||
| }) | ||||
| export class AddonBlockTimelineComponent implements OnInit, ICoreBlockComponent { | ||||
| 
 | ||||
|     sort = new FormControl(); | ||||
|     sort = new FormControl(AddonBlockTimelineSort.ByDates); | ||||
|     sort$!: Observable<AddonBlockTimelineSort>; | ||||
|     sortOptions!: AddonBlockTimelineOption<AddonBlockTimelineSort>[]; | ||||
|     filter = new FormControl(); | ||||
|     filter = new FormControl(AddonBlockTimelineFilter.Next30Days); | ||||
|     filter$!: Observable<AddonBlockTimelineFilter>; | ||||
|     statusFilterOptions!: AddonBlockTimelineOption<AddonBlockTimelineFilter>[]; | ||||
|     dateFilterOptions!: AddonBlockTimelineOption<AddonBlockTimelineFilter>[]; | ||||
|  | ||||
| @ -78,9 +78,9 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave { | ||||
| 
 | ||||
|     // Form variables.
 | ||||
|     form: FormGroup; | ||||
|     typeControl: FormControl; | ||||
|     groupControl: FormControl; | ||||
|     descriptionControl: FormControl; | ||||
|     typeControl: FormControl<AddonCalendarEventType | null>; | ||||
|     groupControl: FormControl<number | null>; | ||||
|     descriptionControl: FormControl<string>; | ||||
| 
 | ||||
|     // Reminders.
 | ||||
|     remindersEnabled = false; | ||||
| @ -103,9 +103,9 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave { | ||||
|         this.form = new FormGroup({}); | ||||
| 
 | ||||
|         // Initialize form variables.
 | ||||
|         this.typeControl = this.fb.control('', Validators.required); | ||||
|         this.groupControl = this.fb.control(''); | ||||
|         this.descriptionControl = this.fb.control(''); | ||||
|         this.typeControl = this.fb.control(null, Validators.required); | ||||
|         this.groupControl = this.fb.control(null); | ||||
|         this.descriptionControl = this.fb.control('', { nonNullable: true }); | ||||
|         this.form.addControl('name', this.fb.control('', Validators.required)); | ||||
|         this.form.addControl('eventtype', this.typeControl); | ||||
|         this.form.addControl('categoryid', this.fb.control('')); | ||||
| @ -322,11 +322,11 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave { | ||||
| 
 | ||||
|         this.form.controls.name.setValue(event.name); | ||||
|         this.form.controls.timestart.setValue(CoreTimeUtils.toDatetimeFormat(event.timestart * 1000)); | ||||
|         this.form.controls.eventtype.setValue(event.eventtype); | ||||
|         this.typeControl.setValue(event.eventtype as AddonCalendarEventType); | ||||
|         this.form.controls.categoryid.setValue(event.categoryid || ''); | ||||
|         this.form.controls.courseid.setValue(courseId || ''); | ||||
|         this.form.controls.groupcourseid.setValue(courseId || ''); | ||||
|         this.form.controls.groupid.setValue(event.groupid || ''); | ||||
|         this.groupControl.setValue(event.groupid || null); | ||||
|         this.form.controls.description.setValue(event.description); | ||||
|         this.form.controls.location.setValue(event.location); | ||||
| 
 | ||||
| @ -410,7 +410,7 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave { | ||||
|         try { | ||||
|             await this.loadGroups(courseId); | ||||
| 
 | ||||
|             this.groupControl.setValue(''); | ||||
|             this.groupControl.setValue(null); | ||||
|         } catch (error) { | ||||
|             CoreDomUtils.showErrorModalDefault(error, 'Error getting data.'); | ||||
|         } | ||||
|  | ||||
| @ -34,7 +34,7 @@ import { AddonModAssignFeedbackPluginBaseComponent } from '@addons/mod/assign/cl | ||||
| }) | ||||
| export class AddonModAssignFeedbackCommentsComponent extends AddonModAssignFeedbackPluginBaseComponent implements OnInit { | ||||
| 
 | ||||
|     control?: FormControl; | ||||
|     control?: FormControl<string>; | ||||
|     component = AddonModAssignProvider.COMPONENT; | ||||
|     text = ''; | ||||
|     isSent = false; | ||||
| @ -76,7 +76,7 @@ export class AddonModAssignFeedbackCommentsComponent extends AddonModAssignFeedb | ||||
|                     } | ||||
|                 }); | ||||
|             } else if (this.edit) { | ||||
|                 this.control = this.fb.control(this.text); | ||||
|                 this.control = this.fb.control(this.text, { nonNullable: true }); | ||||
|             } | ||||
|         } finally { | ||||
|             this.loaded = true; | ||||
|  | ||||
| @ -31,7 +31,7 @@ import { AddonModAssignSubmissionOnlineTextPluginData } from '../services/handle | ||||
| }) | ||||
| export class AddonModAssignSubmissionOnlineTextComponent extends AddonModAssignSubmissionPluginBaseComponent implements OnInit { | ||||
| 
 | ||||
|     control?: FormControl; | ||||
|     control?: FormControl<string>; | ||||
|     words = 0; | ||||
|     component = AddonModAssignProvider.COMPONENT; | ||||
|     text = ''; | ||||
| @ -94,7 +94,7 @@ export class AddonModAssignSubmissionOnlineTextComponent extends AddonModAssignS | ||||
|                 }); | ||||
|             } else { | ||||
|                 // Create and add the control.
 | ||||
|                 this.control = this.fb.control(this.text); | ||||
|                 this.control = this.fb.control(this.text, { nonNullable: true }); | ||||
|             } | ||||
| 
 | ||||
|             // Calculate initial words.
 | ||||
|  | ||||
| @ -83,7 +83,7 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges | ||||
| 
 | ||||
|     @ViewChild('replyFormEl') formElement!: ElementRef; | ||||
| 
 | ||||
|     messageControl = new FormControl(); | ||||
|     messageControl = new FormControl<string | null>(null); | ||||
| 
 | ||||
|     uniqueId!: string; | ||||
|     defaultReplySubject!: string; | ||||
|  | ||||
| @ -70,7 +70,7 @@ export class AddonModForumNewDiscussionPage implements OnInit, OnDestroy, CanLea | ||||
|     @ViewChild(CoreEditorRichTextEditorComponent) messageEditor!: CoreEditorRichTextEditorComponent; | ||||
| 
 | ||||
|     component = AddonModForumProvider.COMPONENT; | ||||
|     messageControl = new FormControl(); | ||||
|     messageControl = new FormControl<string | null>(null); | ||||
|     groupsLoaded = false; | ||||
|     showGroups = false; | ||||
|     hasOffline = false; | ||||
|  | ||||
| @ -58,7 +58,7 @@ export class AddonModGlossaryEditPage implements OnInit, CanLeave { | ||||
|     courseId!: number; | ||||
|     loaded = false; | ||||
|     glossary?: AddonModGlossaryGlossary; | ||||
|     definitionControl = new FormControl(); | ||||
|     definitionControl = new FormControl<string | null>(null); | ||||
|     categories: AddonModGlossaryCategory[] = []; | ||||
|     showAliases = true; | ||||
|     editorExtraParams: Record<string, unknown> = {}; | ||||
|  | ||||
| @ -369,7 +369,7 @@ export class AddonModLessonHelperProvider { | ||||
|             }; | ||||
| 
 | ||||
|             // Init the control.
 | ||||
|             essayQuestion.control = this.formBuilder.control(''); | ||||
|             essayQuestion.control = this.formBuilder.control('', { nonNullable: true }); | ||||
|             questionForm.addControl(essayQuestion.textarea.name, essayQuestion.control); | ||||
|         } | ||||
| 
 | ||||
| @ -635,7 +635,7 @@ export type AddonModLessonInputQuestion = AddonModLessonQuestionBasicData & { | ||||
| export type AddonModLessonEssayQuestion = AddonModLessonQuestionBasicData & { | ||||
|     useranswer?: string; // User answer, for reviewing.
 | ||||
|     textarea?: AddonModLessonTextareaData; // Data for the textarea.
 | ||||
|     control?: FormControl; // Form control.
 | ||||
|     control?: FormControl<string>; // Form control.
 | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  | ||||
| @ -47,7 +47,7 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy, CanLeave { | ||||
|     courseId?: number; // Course the wiki belongs to.
 | ||||
|     title?: string; // Title to display.
 | ||||
|     pageForm: FormGroup; // The form group.
 | ||||
|     contentControl: FormControl; // The FormControl for the page content.
 | ||||
|     contentControl: FormControl<string>; // The FormControl for the page content.
 | ||||
|     canEditTitle = false; // Whether title can be edited.
 | ||||
|     loaded = false; // Whether the data has been loaded.
 | ||||
|     component = AddonModWikiProvider.COMPONENT; // Component to link the files to.
 | ||||
| @ -74,7 +74,7 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy, CanLeave { | ||||
|     constructor( | ||||
|         protected formBuilder: FormBuilder, | ||||
|     ) { | ||||
|         this.contentControl = this.formBuilder.control(''); | ||||
|         this.contentControl = this.formBuilder.control('', { nonNullable: true }); | ||||
|         this.pageForm = this.formBuilder.group({}); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -73,7 +73,7 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit, OnDe | ||||
|     assessmentStrategyLoaded = false; | ||||
|     notSupported = false; | ||||
|     feedbackText = ''; | ||||
|     feedbackControl = new FormControl(); | ||||
|     feedbackControl = new FormControl<string | null>(null); | ||||
|     overallFeedkback = false; | ||||
|     overallFeedkbackRequired = false; | ||||
|     component = ADDON_MOD_WORKSHOP_COMPONENT; | ||||
|  | ||||
| @ -32,7 +32,7 @@ import { CoreFileEntry } from '@services/file-helper'; | ||||
| }) | ||||
| export class AddonQtypeEssayComponent extends CoreQuestionBaseComponent<AddonModQuizEssayQuestion> { | ||||
| 
 | ||||
|     formControl?: FormControl; | ||||
|     formControl?: FormControl<string | null>; | ||||
|     attachments?: CoreFileEntry[]; | ||||
|     uploadFilesSupported = false; | ||||
| 
 | ||||
| @ -52,7 +52,7 @@ export class AddonQtypeEssayComponent extends CoreQuestionBaseComponent<AddonMod | ||||
| 
 | ||||
|         this.initEssayComponent(this.review); | ||||
| 
 | ||||
|         this.formControl = this.fb.control(this.question?.textarea?.text); | ||||
|         this.formControl = this.fb.control(this.question?.textarea?.text ?? null); | ||||
| 
 | ||||
|         if (this.question?.allowsAttachments && this.uploadFilesSupported && !this.review) { | ||||
|             this.loadAttachments(); | ||||
|  | ||||
| @ -27,20 +27,23 @@ import { CoreUtils } from '@services/utils/utils'; | ||||
|     templateUrl: 'addon-user-profile-field-checkbox.html', | ||||
|     styleUrls: ['./checkbox.scss'], | ||||
| }) | ||||
| export class AddonUserProfileFieldCheckboxComponent extends CoreUserProfileFieldBaseComponent { | ||||
| export class AddonUserProfileFieldCheckboxComponent extends CoreUserProfileFieldBaseComponent<boolean> { | ||||
| 
 | ||||
|     /** | ||||
|      * Create the Form control. | ||||
|      * | ||||
|      * @returns Form control. | ||||
|      */ | ||||
|     protected createFormControl(field: AuthEmailSignupProfileField): FormControl { | ||||
|     protected createFormControl(field: AuthEmailSignupProfileField): FormControl<boolean> { | ||||
|         const formData = { | ||||
|             value: CoreUtils.isTrueOrOne(field.defaultdata), | ||||
|             disabled: this.disabled, | ||||
|         }; | ||||
| 
 | ||||
|         return new FormControl(formData, this.required && !field.locked ? Validators.requiredTrue : null); | ||||
|         return new FormControl(formData, { | ||||
|             validators: this.required && !field.locked ? Validators.requiredTrue : null, | ||||
|             nonNullable: true, | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -28,7 +28,7 @@ import { CoreUserProfileFieldBaseComponent } from '@features/user/classes/base-p | ||||
|     selector: 'addon-user-profile-field-datetime', | ||||
|     templateUrl: 'addon-user-profile-field-datetime.html', | ||||
| }) | ||||
| export class AddonUserProfileFieldDatetimeComponent extends CoreUserProfileFieldBaseComponent { | ||||
| export class AddonUserProfileFieldDatetimeComponent extends CoreUserProfileFieldBaseComponent<string | undefined> { | ||||
| 
 | ||||
|     ionDateTimePresentation = 'date'; | ||||
|     min?: string; | ||||
| @ -84,13 +84,16 @@ export class AddonUserProfileFieldDatetimeComponent extends CoreUserProfileField | ||||
|      * | ||||
|      * @returns Form control. | ||||
|      */ | ||||
|     protected createFormControl(field: AuthEmailSignupProfileField): FormControl { | ||||
|     protected createFormControl(field: AuthEmailSignupProfileField): FormControl<string | undefined> { | ||||
|         const formData = { | ||||
|             value: field.defaultdata != '0' ? field.defaultdata : undefined, | ||||
|             disabled: this.disabled, | ||||
|         }; | ||||
| 
 | ||||
|         return new FormControl(formData, this.required && !field.locked ? Validators.required : null); | ||||
|         return new FormControl(formData, { | ||||
|             validators: this.required && !field.locked ? Validators.required : null, | ||||
|             nonNullable: true, | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -40,7 +40,7 @@ import { FormControl } from '@angular/forms'; | ||||
| }) | ||||
| export class CoreInputErrorsComponent implements OnInit, OnChanges { | ||||
| 
 | ||||
|     @Input() control?: FormControl; // Needed to be able to check the validity of the input.
 | ||||
|     @Input() control?: FormControl<unknown>; // Needed to be able to check the validity of the input.
 | ||||
|     @Input() errorMessages: Record<string, string> = {}; // Error messages to show. Keys must be the name of the error.
 | ||||
|     @Input() errorText = ''; // Set other non automatic errors.
 | ||||
|     errorKeys: string[] = []; | ||||
|  | ||||
| @ -66,7 +66,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterViewInit, | ||||
|     // @todo Implement ControlValueAccessor https://angular.io/api/forms/ControlValueAccessor.
 | ||||
| 
 | ||||
|     @Input() placeholder = ''; // Placeholder to set in textarea.
 | ||||
|     @Input() control?: FormControl; // Form control.
 | ||||
|     @Input() control?: FormControl<string | undefined | null>; // Form control.
 | ||||
|     @Input() name = 'core-rich-text-editor'; // Name to set to the textarea.
 | ||||
|     @Input() component?: string; // The component to link the files to.
 | ||||
|     @Input() componentId?: number; // An ID to use in conjunction with the component.
 | ||||
| @ -75,7 +75,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterViewInit, | ||||
|     @Input() contextInstanceId?: number; // The instance ID related to the context.
 | ||||
|     @Input() elementId?: string; // An ID to set to the element.
 | ||||
|     @Input() draftExtraParams?: Record<string, unknown>; // Extra params to identify the draft.
 | ||||
|     @Output() contentChanged: EventEmitter<string>; | ||||
|     @Output() contentChanged: EventEmitter<string | undefined | null>; | ||||
| 
 | ||||
|     @ViewChild('editor') editor?: ElementRef; // WYSIWYG editor.
 | ||||
|     @ViewChild('textarea') textarea?: IonTextarea; // Textarea editor.
 | ||||
| @ -190,8 +190,8 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterViewInit, | ||||
|         // Setup the editor.
 | ||||
|         this.editorElement = this.editor?.nativeElement as HTMLDivElement; | ||||
|         this.setContent(this.control?.value); | ||||
|         this.originalContent = this.control?.value; | ||||
|         this.lastDraft = this.control?.value; | ||||
|         this.originalContent = this.control?.value ?? undefined; | ||||
|         this.lastDraft = this.control?.value ?? ''; | ||||
| 
 | ||||
|         // Use paragraph on enter.
 | ||||
|         // eslint-disable-next-line deprecation/deprecation
 | ||||
| @ -261,19 +261,19 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterViewInit, | ||||
| 
 | ||||
|             // Apply the new content.
 | ||||
|             this.setContent(newValue); | ||||
|             this.originalContent = newValue; | ||||
|             this.originalContent = newValue ?? undefined; | ||||
|             this.infoMessage = undefined; | ||||
| 
 | ||||
|             // Save a draft so the original content is saved.
 | ||||
|             this.lastDraft = newValue; | ||||
|             this.lastDraft = newValue ?? ''; | ||||
|             CoreEditorOffline.saveDraft( | ||||
|                 this.contextLevel || '', | ||||
|                 this.contextInstanceId || 0, | ||||
|                 this.elementId || '', | ||||
|                 this.draftExtraParams || {}, | ||||
|                 this.pageInstance, | ||||
|                 newValue, | ||||
|                 newValue, | ||||
|                 this.lastDraft, | ||||
|                 this.originalContent, | ||||
|             ); | ||||
|         }); | ||||
| 
 | ||||
| @ -579,7 +579,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterViewInit, | ||||
|      * @param value text | ||||
|      * @returns If value is null only a white space. | ||||
|      */ | ||||
|     protected isNullOrWhiteSpace(value: string | null): boolean { | ||||
|     protected isNullOrWhiteSpace(value: string | null | undefined): boolean { | ||||
|         if (value == null || value === undefined) { | ||||
|             return true; | ||||
|         } | ||||
| @ -595,7 +595,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterViewInit, | ||||
|      * | ||||
|      * @param value New content. | ||||
|      */ | ||||
|     protected setContent(value: string | null): void { | ||||
|     protected setContent(value: string | null | undefined): void { | ||||
|         if (!this.editorElement || !this.textarea) { | ||||
|             return; | ||||
|         } | ||||
| @ -974,7 +974,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterViewInit, | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             const newText = this.control.value; | ||||
|             const newText = this.control.value ?? ''; | ||||
| 
 | ||||
|             if (this.lastDraft == newText) { | ||||
|                 // Text hasn't changed, nothing to save.
 | ||||
|  | ||||
| @ -69,8 +69,8 @@ export class CoreLoginEmailSignupPage implements OnInit { | ||||
| 
 | ||||
|     // Data for age verification.
 | ||||
|     ageVerificationForm: FormGroup; | ||||
|     countryControl: FormControl; | ||||
|     signUpCountryControl?: FormControl; | ||||
|     countryControl: FormControl<string>; | ||||
|     signUpCountryControl?: FormControl<string>; | ||||
|     isMinor = false; // Whether the user is minor age.
 | ||||
|     ageDigitalConsentVerification?: boolean; // Whether the age verification is enabled.
 | ||||
|     supportName?: string; | ||||
| @ -93,7 +93,7 @@ export class CoreLoginEmailSignupPage implements OnInit { | ||||
|         this.ageVerificationForm = this.fb.group({ | ||||
|             age: ['', Validators.required], | ||||
|         }); | ||||
|         this.countryControl = this.fb.control('', Validators.required); | ||||
|         this.countryControl = this.fb.control('', { validators: Validators.required, nonNullable: true }); | ||||
|         this.ageVerificationForm.addControl('country', this.countryControl); | ||||
| 
 | ||||
|         // Create the signupForm with the basic controls. More controls will be added later.
 | ||||
| @ -141,7 +141,7 @@ export class CoreLoginEmailSignupPage implements OnInit { | ||||
|      */ | ||||
|     protected completeFormGroup(): void { | ||||
|         this.signupForm.addControl('city', this.fb.control(this.settings?.defaultcity || '')); | ||||
|         this.signUpCountryControl = this.fb.control(this.settings?.country || ''); | ||||
|         this.signUpCountryControl = this.fb.control(this.settings?.country || '', { nonNullable: true }); | ||||
|         this.signupForm.addControl('country', this.signUpCountryControl); | ||||
| 
 | ||||
|         // Add the name fields.
 | ||||
|  | ||||
| @ -24,7 +24,7 @@ import { CoreUserProfileField } from '@features/user/services/user'; | ||||
| @Component({ | ||||
|     template: '', | ||||
| }) | ||||
| export abstract class CoreUserProfileFieldBaseComponent implements OnInit { | ||||
| export abstract class CoreUserProfileFieldBaseComponent<T = string> implements OnInit { | ||||
| 
 | ||||
|     @Input() field?: AuthEmailSignupProfileField | CoreUserProfileField; // The profile field to be rendered.
 | ||||
|     @Input() signup = false; // True if editing the field in signup. Defaults to false.
 | ||||
| @ -36,7 +36,7 @@ export abstract class CoreUserProfileFieldBaseComponent implements OnInit { | ||||
|     @Input() contextInstanceId?: number; // The instance ID related to the context.
 | ||||
|     @Input() courseId?: number; // Course ID the field belongs to (if any). It can be used to improve performance with filters.
 | ||||
| 
 | ||||
|     control?: FormControl; | ||||
|     control?: FormControl<T>; | ||||
|     modelName = ''; | ||||
|     value?: string; | ||||
|     required?: boolean; | ||||
| @ -91,13 +91,16 @@ export abstract class CoreUserProfileFieldBaseComponent implements OnInit { | ||||
|      * | ||||
|      * @returns Form control. | ||||
|      */ | ||||
|     protected createFormControl(field: AuthEmailSignupProfileField): FormControl { | ||||
|     protected createFormControl(field: AuthEmailSignupProfileField): FormControl<T> { | ||||
|         const formData = { | ||||
|             value: field.defaultdata, | ||||
|             value: (field.defaultdata ?? '') as T, | ||||
|             disabled: this.disabled, | ||||
|         }; | ||||
| 
 | ||||
|         return new FormControl(formData, this.required && !field.locked ? Validators.required : null); | ||||
|         return new FormControl(formData, { | ||||
|             validators: this.required && !field.locked ? Validators.required : null, | ||||
|             nonNullable: true, | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -22,10 +22,10 @@ import { catchError, filter } from 'rxjs/operators'; | ||||
|  * @param control Form control. | ||||
|  * @returns Form control value observable. | ||||
|  */ | ||||
| export function formControlValue<T = unknown>(control: FormControl): Observable<T> { | ||||
| export function formControlValue<T = unknown>(control: FormControl<T | null>): Observable<T> { | ||||
|     return control.valueChanges.pipe( | ||||
|         startWithOnSubscribed(() => control.value), | ||||
|         filter(value => value !== null), | ||||
|         filter((value): value is T => value !== null), | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user