Merge pull request #1648 from dpalou/MOBILE-2610

MOBILE-2610 ios: Prevent app reset when submit form
main
Juan Leyva 2018-12-04 11:46:43 +01:00 committed by GitHub
commit 8248890189
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 114 additions and 35 deletions

View File

@ -11,6 +11,6 @@
<ion-content> <ion-content>
<form name="addon-mod_assign-edit-feedback-form" *ngIf="userId && plugin"> <form name="addon-mod_assign-edit-feedback-form" *ngIf="userId && plugin">
<addon-mod-assign-feedback-plugin [assign]="assign" [submission]="submission" [userId]="userId" [plugin]="plugin" [edit]="true"></addon-mod-assign-feedback-plugin> <addon-mod-assign-feedback-plugin [assign]="assign" [submission]="submission" [userId]="userId" [plugin]="plugin" [edit]="true"></addon-mod-assign-feedback-plugin>
<button ion-button block (click)="done()">{{ 'core.done' | translate }}</button> <button ion-button block (click)="done($event)">{{ 'core.done' | translate }}</button>
</form> </form>
</ion-content> </ion-content>

View File

@ -72,8 +72,13 @@ export class AddonModAssignEditFeedbackModalPage {
/** /**
* Done editing. * Done editing.
*
* @param {Event} e Click event.
*/ */
done(): void { done(e: Event): void {
e.preventDefault();
e.stopPropagation();
// Close the modal, sending the input data. // Close the modal, sending the input data.
this.forceLeave = true; this.forceLeave = true;
this.closeModal(this.getInputData()); this.closeModal(this.getInputData());

View File

@ -23,7 +23,7 @@
{{ cssTemplate }} {{ cssTemplate }}
</style> </style>
<form (ngSubmit)="save()" [formGroup]="editForm"> <form (ngSubmit)="save($event)" [formGroup]="editForm">
<core-compile-html [text]="editFormRender" [jsData]="jsData" [extraImports]="extraImports"></core-compile-html> <core-compile-html [text]="editFormRender" [jsData]="jsData" [extraImports]="extraImports"></core-compile-html>
</form> </form>
</div> </div>

View File

@ -185,9 +185,13 @@ export class AddonModDataEditPage {
/** /**
* Saves data. * Saves data.
* *
* @param {Event} e Event.
* @return {Promise<any>} Resolved when done. * @return {Promise<any>} Resolved when done.
*/ */
save(): Promise<any> { save(e: Event): Promise<any> {
e.preventDefault();
e.stopPropagation();
const inputData = this.editForm.value; const inputData = this.editForm.value;
return this.dataHelper.hasEditDataChanged(inputData, this.fieldsArray, this.data.id, return this.dataHelper.hasEditDataChanged(inputData, this.fieldsArray, this.data.id,

View File

@ -13,7 +13,7 @@
<a class="tab-slide" [attr.aria-selected]="!search.searchingAdvanced" (click)="toggleAdvanced()">{{ 'addon.mod_data.search' | translate}}</a> <a class="tab-slide" [attr.aria-selected]="!search.searchingAdvanced" (click)="toggleAdvanced()">{{ 'addon.mod_data.search' | translate}}</a>
<a class="tab-slide" [attr.aria-selected]="search.searchingAdvanced" (click)="toggleAdvanced()">{{ 'addon.mod_data.advancedsearch' | translate }}</a> <a class="tab-slide" [attr.aria-selected]="search.searchingAdvanced" (click)="toggleAdvanced()">{{ 'addon.mod_data.advancedsearch' | translate }}</a>
</div> </div>
<form (ngSubmit)="searchEntries()" [formGroup]="searchForm"> <form (ngSubmit)="searchEntries($event)" [formGroup]="searchForm">
<ion-list no-margin> <ion-list no-margin>
<ion-item [hidden]="search.searchingAdvanced"> <ion-item [hidden]="search.searchingAdvanced">
<ion-input type="text" placeholder="{{ 'addon.mod_data.search' | translate}}" [(ngModel)]="search.text" name="text" formControlName="text"></ion-input> <ion-input type="text" placeholder="{{ 'addon.mod_data.search' | translate}}" [(ngModel)]="search.text" name="text" formControlName="text"></ion-input>

View File

@ -183,8 +183,13 @@ export class AddonModDataSearchPage {
/** /**
* Done editing. * Done editing.
*
* @param {Event} e Event.
*/ */
searchEntries(): void { searchEntries(e: Event): void {
e.preventDefault();
e.stopPropagation();
const searchedData = this.searchForm.value; const searchedData = this.searchForm.value;
if (this.search.searchingAdvanced) { if (this.search.searchingAdvanced) {

View File

@ -33,7 +33,7 @@
<!-- Input password for protected lessons. --> <!-- Input password for protected lessons. -->
<ion-card *ngIf="askPassword"> <ion-card *ngIf="askPassword">
<form ion-list (ngSubmit)="submitPassword(passwordinput)"> <form ion-list (ngSubmit)="submitPassword($event, passwordinput)">
<ion-item> <ion-item>
<core-show-password item-content [name]="'password'"> <core-show-password item-content [name]="'password'">
<ion-label>{{ 'addon.mod_lesson.enterpassword' | translate }}</ion-label> <ion-label>{{ 'addon.mod_lesson.enterpassword' | translate }}</ion-label>

View File

@ -502,9 +502,13 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
/** /**
* Submit password for password protected lessons. * Submit password for password protected lessons.
* *
* @param {Event} e Event.
* @param {HTMLInputElement} passwordEl The password input. * @param {HTMLInputElement} passwordEl The password input.
*/ */
submitPassword(passwordEl: HTMLInputElement): void { submitPassword(e: Event, passwordEl: HTMLInputElement): void {
e.preventDefault();
e.stopPropagation();
const password = passwordEl && passwordEl.value; const password = passwordEl && passwordEl.value;
if (!password) { if (!password) {
this.domUtils.showErrorModal('addon.mod_lesson.emptypassword', true); this.domUtils.showErrorModal('addon.mod_lesson.emptypassword', true);

View File

@ -9,7 +9,7 @@
</ion-navbar> </ion-navbar>
</ion-header> </ion-header>
<ion-content padding class="addon-mod_lesson-password-modal"> <ion-content padding class="addon-mod_lesson-password-modal">
<form ion-list (ngSubmit)="submitPassword(passwordinput)"> <form ion-list (ngSubmit)="submitPassword($event, passwordinput)">
<ion-item> <ion-item>
<core-show-password item-content [name]="'password'"> <core-show-password item-content [name]="'password'">
<ion-label>{{ 'addon.mod_lesson.enterpassword' | translate }}</ion-label> <ion-label>{{ 'addon.mod_lesson.enterpassword' | translate }}</ion-label>

View File

@ -29,8 +29,14 @@ export class AddonModLessonPasswordModalPage {
/** /**
* Send the password back. * Send the password back.
*
* @param {Event} e Event.
* @param {HTMLInputElement} password The input element.
*/ */
submitPassword(password: HTMLInputElement): void { submitPassword(e: Event, password: HTMLInputElement): void {
e.preventDefault();
e.stopPropagation();
this.viewCtrl.dismiss(password.value); this.viewCtrl.dismiss(password.value);
} }

View File

@ -108,7 +108,7 @@
</ng-container> </ng-container>
<ion-item> <ion-item>
<button ion-button block (click)="submitQuestion()" class="button-no-uppercase">{{ question.submitLabel }}</button> <button ion-button block (click)="submitQuestion($event)" class="button-no-uppercase">{{ question.submitLabel }}</button>
</ion-item> </ion-item>
</form> </form>
</ion-card> </ion-card>

View File

@ -606,8 +606,13 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy {
/** /**
* Submit a question. * Submit a question.
*
* @param {Event} e Event.
*/ */
submitQuestion(): void { submitQuestion(e: Event): void {
e.preventDefault();
e.stopPropagation();
this.loaded = false; this.loaded = false;
// Use getRawValue to include disabled values. // Use getRawValue to include disabled values.

View File

@ -10,7 +10,7 @@
</ion-header> </ion-header>
<ion-content padding class="addon-mod_quiz-preflight-modal"> <ion-content padding class="addon-mod_quiz-preflight-modal">
<core-loading [hideUntil]="loaded"> <core-loading [hideUntil]="loaded">
<form ion-list [formGroup]="preflightForm" (ngSubmit)="sendData()"> <form ion-list [formGroup]="preflightForm" (ngSubmit)="sendData($event)">
<!-- Access rules. --> <!-- Access rules. -->
<ng-container *ngFor="let data of accessRulesData; let last = last"> <ng-container *ngFor="let data of accessRulesData; let last = last">
<core-dynamic-component [component]="data.component" [data]="data.data"> <core-dynamic-component [component]="data.component" [data]="data.data">

View File

@ -98,8 +98,13 @@ export class AddonModQuizPreflightModalPage implements OnInit {
/** /**
* Check that the data is valid and send it back. * Check that the data is valid and send it back.
*
* @param {Event} e Event.
*/ */
sendData(): void { sendData(e: Event): void {
e.preventDefault();
e.stopPropagation();
if (!this.preflightForm.valid) { if (!this.preflightForm.valid) {
// Form not valid. Scroll to the first element with errors. // Form not valid. Scroll to the first element with errors.
if (!this.domUtils.scrollToInputError(this.content)) { if (!this.domUtils.scrollToInputError(this.content)) {

View File

@ -9,7 +9,7 @@
</ion-navbar> </ion-navbar>
</ion-header> </ion-header>
<ion-content padding> <ion-content padding>
<form name="itemEdit" (ngSubmit)="addNote()"> <form name="itemEdit" (ngSubmit)="addNote($event)">
<ion-item> <ion-item>
<ion-label>{{ 'addon.notes.publishstate' | translate }}</ion-label> <ion-label>{{ 'addon.notes.publishstate' | translate }}</ion-label>
<ion-select [(ngModel)]="publishState" name="publishState" interface="popover"> <ion-select [(ngModel)]="publishState" name="publishState" interface="popover">

View File

@ -41,8 +41,13 @@ export class AddonNotesAddPage {
/** /**
* Send the note or store it offline. * Send the note or store it offline.
*
* @param {Event} e Event.
*/ */
addNote(): void { addNote(e: Event): void {
e.preventDefault();
e.stopPropagation();
this.appProvider.closeKeyboard(); this.appProvider.closeKeyboard();
const loadingModal = this.domUtils.showModalLoading('core.sending', true); const loadingModal = this.domUtils.showModalLoading('core.sending', true);
// Freeze the add note button. // Freeze the add note button.

View File

@ -1,5 +1,5 @@
<ion-card> <ion-card>
<form #f="ngForm" (ngSubmit)="submitForm()"> <form #f="ngForm" (ngSubmit)="submitForm($event)">
<ion-item> <ion-item>
<ion-input type="text" name="search" [(ngModel)]="searchText" [placeholder]="placeholder" [autocorrect]="autocorrect" [spellcheck]="spellcheck" [core-auto-focus]="autoFocus" [disabled]="disabled"></ion-input> <ion-input type="text" name="search" [(ngModel)]="searchText" [placeholder]="placeholder" [autocorrect]="autocorrect" [spellcheck]="spellcheck" [core-auto-focus]="autoFocus" [disabled]="disabled"></ion-input>
<button item-end ion-button clear icon-only type="submit" class="button-small" [attr.aria-label]="searchLabel" [disabled]="!searchText || (searchText.length < lengthCheck)" [disabled]="disabled"> <button item-end ion-button clear icon-only type="submit" class="button-small" [attr.aria-label]="searchLabel" [disabled]="!searchText || (searchText.length < lengthCheck)" [disabled]="disabled">

View File

@ -60,9 +60,12 @@ export class CoreSearchBoxComponent implements OnInit {
/** /**
* Form submitted. * Form submitted.
* *
* @param {string} value Entered value. * @param {Event} e Event.
*/ */
submitForm(value: string): void { submitForm(e: Event): void {
e.preventDefault();
e.stopPropagation();
if (this.searchText.length < this.lengthCheck) { if (this.searchText.length < this.lengthCheck) {
// The view should handle this case, but we check it here too just in case. // The view should handle this case, but we check it here too just in case.
return; return;

View File

@ -10,7 +10,7 @@
</ion-navbar> </ion-navbar>
</ion-header> </ion-header>
<ion-content> <ion-content>
<form ion-list #f="ngForm" (ngSubmit)="submitPassword(f.value.password)"> <form ion-list #f="ngForm" (ngSubmit)="submitPassword($event, f.value.password)">
<ion-item> <ion-item>
<core-show-password item-content [name]="'password'"> <core-show-password item-content [name]="'password'">
<ion-input text-wrap class="core-ioninput-password" name="password" type="password" placeholder="{{ 'core.courses.password' | translate }}" ngModel [core-auto-focus] [clearOnEdit]="false"></ion-input> <ion-input text-wrap class="core-ioninput-password" name="password" type="password" placeholder="{{ 'core.courses.password' | translate }}" ngModel [core-auto-focus] [clearOnEdit]="false"></ion-input>

View File

@ -36,9 +36,13 @@ export class CoreCoursesSelfEnrolPasswordPage {
/** /**
* Submit password. * Submit password.
* *
* @param {Event} e Event.
* @param {string} password Password to submit. * @param {string} password Password to submit.
*/ */
submitPassword(password: string): void { submitPassword(e: Event, password: string): void {
e.preventDefault();
e.stopPropagation();
this.viewCtrl.dismiss(password); this.viewCtrl.dismiss(password);
} }
} }

View File

@ -23,7 +23,7 @@
<p *ngIf="siteName" padding class="item-heading core-sitename"><core-format-text [text]="siteName"></core-format-text></p> <p *ngIf="siteName" padding class="item-heading core-sitename"><core-format-text [text]="siteName"></core-format-text></p>
<p *ngIf="siteName" class="core-siteurl">{{siteUrl}}</p> <p *ngIf="siteName" class="core-siteurl">{{siteUrl}}</p>
</div> </div>
<form ion-list [formGroup]="credForm" (ngSubmit)="login()"> <form ion-list [formGroup]="credForm" (ngSubmit)="login($event)">
<ion-item *ngIf="siteChecked && !isBrowserSSO"> <ion-item *ngIf="siteChecked && !isBrowserSSO">
<ion-input type="text" name="username" placeholder="{{ 'core.login.username' | translate }}" formControlName="username" autocapitalize="none" autocorrect="off"></ion-input> <ion-input type="text" name="username" placeholder="{{ 'core.login.username' | translate }}" formControlName="username" autocapitalize="none" autocorrect="off"></ion-input>
</ion-item> </ion-item>

View File

@ -163,8 +163,15 @@ export class CoreLoginCredentialsPage {
/** /**
* Tries to authenticate the user. * Tries to authenticate the user.
*
* @param {Event} [e] Event.
*/ */
login(): void { login(e?: Event): void {
if (e) {
e.preventDefault();
e.stopPropagation();
}
this.appProvider.closeKeyboard(); this.appProvider.closeKeyboard();
// Get input data. // Get input data.

View File

@ -17,7 +17,7 @@
<core-loading [hideUntil]="settingsLoaded" *ngIf="!isMinor"> <core-loading [hideUntil]="settingsLoaded" *ngIf="!isMinor">
<!-- Age verification. --> <!-- Age verification. -->
<form ion-list *ngIf="settingsLoaded && settings && ageDigitalConsentVerification" [formGroup]="ageVerificationForm" (ngSubmit)="verifyAge()"> <form ion-list *ngIf="settingsLoaded && settings && ageDigitalConsentVerification" [formGroup]="ageVerificationForm" (ngSubmit)="verifyAge($event)">
<ion-item-divider color="light" text-wrap> <ion-item-divider color="light" text-wrap>
<p class="item-heading">{{ 'core.agelocationverification' | translate }}</p> <p class="item-heading">{{ 'core.agelocationverification' | translate }}</p>
</ion-item-divider> </ion-item-divider>
@ -47,7 +47,7 @@
</form> </form>
<!-- Signup form. --> <!-- Signup form. -->
<form ion-list *ngIf="settingsLoaded && settings && !ageDigitalConsentVerification" [formGroup]="signupForm" (ngSubmit)="create()"> <form ion-list *ngIf="settingsLoaded && settings && !ageDigitalConsentVerification" [formGroup]="signupForm" (ngSubmit)="create($event)">
<ion-item text-wrap text-center> <ion-item text-wrap text-center>
<!-- If no sitename show big siteurl. --> <!-- If no sitename show big siteurl. -->
<p *ngIf="!siteName" padding class="item-heading">{{siteUrl}}</p> <p *ngIf="!siteName" padding class="item-heading">{{siteUrl}}</p>

View File

@ -221,8 +221,13 @@ export class CoreLoginEmailSignupPage {
/** /**
* Create account. * Create account.
*
* @param {Event} e Event.
*/ */
create(): void { create(e: Event): void {
e.preventDefault();
e.stopPropagation();
if (!this.signupForm.valid || (this.settings.recaptchapublickey && !this.captcha.recaptcharesponse)) { if (!this.signupForm.valid || (this.settings.recaptchapublickey && !this.captcha.recaptcharesponse)) {
// Form not valid. Scroll to the first element with errors. // Form not valid. Scroll to the first element with errors.
if (!this.domUtils.scrollToInputError(this.content)) { if (!this.domUtils.scrollToInputError(this.content)) {
@ -309,8 +314,13 @@ export class CoreLoginEmailSignupPage {
/** /**
* Verify Age. * Verify Age.
*
* @param {Event} e Event.
*/ */
verifyAge(): void { verifyAge(e: Event): void {
e.preventDefault();
e.stopPropagation();
if (!this.ageVerificationForm.valid) { if (!this.ageVerificationForm.valid) {
this.domUtils.showErrorModal('core.errorinvalidform', true); this.domUtils.showErrorModal('core.errorinvalidform', true);

View File

@ -10,7 +10,7 @@
</ion-item> </ion-item>
</ion-list> </ion-list>
<ion-card> <ion-card>
<form ion-list [formGroup]="myForm" (ngSubmit)="resetPassword()"> <form ion-list [formGroup]="myForm" (ngSubmit)="resetPassword($event)">
<ion-item-divider text-wrap color="light"> <ion-item-divider text-wrap color="light">
{{ 'core.login.searchby' | translate }} {{ 'core.login.searchby' | translate }}
</ion-item-divider> </ion-item-divider>

View File

@ -43,8 +43,13 @@ export class CoreLoginForgottenPasswordPage {
/** /**
* Request to reset the password. * Request to reset the password.
*
* @param {Event} e Event.
*/ */
resetPassword(): void { resetPassword(e: Event): void {
e.preventDefault();
e.stopPropagation();
const field = this.myForm.value.field, const field = this.myForm.value.field,
value = this.myForm.value.value; value = this.myForm.value.value;

View File

@ -30,7 +30,7 @@
<p class="item-heading">{{ 'core.login.username' | translate }}</p> <p class="item-heading">{{ 'core.login.username' | translate }}</p>
<p>{{username}}</p> <p>{{username}}</p>
</ion-item> </ion-item>
<form [formGroup]="credForm" (ngSubmit)="login()"> <form [formGroup]="credForm" (ngSubmit)="login($event)">
<ion-item margin-bottom> <ion-item margin-bottom>
<core-show-password item-content [name]="'password'"> <core-show-password item-content [name]="'password'">
<ion-input class="core-ioninput-password" name="password" type="password" placeholder="{{ 'core.login.password' | translate }}" formControlName="password" [clearOnEdit]="false"></ion-input> <ion-input class="core-ioninput-password" name="password" type="password" placeholder="{{ 'core.login.password' | translate }}" formControlName="password" [clearOnEdit]="false"></ion-input>

View File

@ -110,8 +110,13 @@ export class CoreLoginReconnectPage {
/** /**
* Tries to authenticate the user. * Tries to authenticate the user.
*
* @param {Event} e Event.
*/ */
login(): void { login(e: Event): void {
e.preventDefault();
e.stopPropagation();
this.appProvider.closeKeyboard(); this.appProvider.closeKeyboard();
// Get input data. // Get input data.

View File

@ -17,7 +17,7 @@
<div text-center padding> <div text-center padding>
<img src="assets/img/login_logo.png" class="avatar-full login-logo" role="presentation"> <img src="assets/img/login_logo.png" class="avatar-full login-logo" role="presentation">
</div> </div>
<form ion-list [formGroup]="siteForm" (ngSubmit)="connect(siteForm.value.siteUrl)" *ngIf="!fixedSites || fixedDisplay == 'select'"> <form ion-list [formGroup]="siteForm" (ngSubmit)="connect($event, siteForm.value.siteUrl)" *ngIf="!fixedSites || fixedDisplay == 'select'">
<!-- Form to input the site URL if there are no fixed sites. --> <!-- Form to input the site URL if there are no fixed sites. -->
<ng-container *ngIf="!fixedSites"> <ng-container *ngIf="!fixedSites">
<p padding>{{ 'core.login.newsitedescription' | translate }}</p> <p padding>{{ 'core.login.newsitedescription' | translate }}</p>
@ -40,7 +40,7 @@
<p class="padding no-padding-bottom">{{ 'core.login.selectsite' | translate }}</p> <p class="padding no-padding-bottom">{{ 'core.login.selectsite' | translate }}</p>
<ion-searchbar *ngIf="fixedSites.length > 4" [(ngModel)]="filter" (ionInput)="filterChanged($event)" (ionCancel)="filterChanged()" [placeholder]="'core.login.findyoursite' | translate"></ion-searchbar> <ion-searchbar *ngIf="fixedSites.length > 4" [(ngModel)]="filter" (ionInput)="filterChanged($event)" (ionCancel)="filterChanged()" [placeholder]="'core.login.findyoursite' | translate"></ion-searchbar>
<ion-item *ngFor="let site of filteredSites" (click)="connect(site.url)" [title]="site.name" detail-push text-wrap> <ion-item *ngFor="let site of filteredSites" (click)="connect($event, site.url)" [title]="site.name" detail-push text-wrap>
<h2>{{site.name}}</h2> <h2>{{site.name}}</h2>
<p>{{site.url}}</p> <p>{{site.url}}</p>
</ion-item> </ion-item>
@ -49,7 +49,7 @@
<!-- Display them using buttons. --> <!-- Display them using buttons. -->
<div *ngIf="fixedSites && fixedDisplay == 'buttons'"> <div *ngIf="fixedSites && fixedDisplay == 'buttons'">
<p class="padding no-padding-bottom">{{ 'core.login.selectsite' | translate }}</p> <p class="padding no-padding-bottom">{{ 'core.login.selectsite' | translate }}</p>
<a *ngFor="let site of fixedSites" ion-button block (click)="connect(site.url)" [title]="site.name" margin-bottom>{{site.name}}</a> <a *ngFor="let site of fixedSites" ion-button block (click)="connect($event, site.url)" [title]="site.name" margin-bottom>{{site.name}}</a>
</div> </div>
</div> </div>
</ion-content> </ion-content>

View File

@ -64,8 +64,14 @@ export class CoreLoginSitePage {
/** /**
* Try to connect to a site. * Try to connect to a site.
*
* @param {Event} e Event.
* @param {string} url The URL to connect to.
*/ */
connect(url: string): void { connect(e: Event, url: string): void {
e.preventDefault();
e.stopPropagation();
this.appProvider.closeKeyboard(); this.appProvider.closeKeyboard();
if (!url) { if (!url) {