Skip to content

Commit

Permalink
feat(core/material/forms): Added visual cues and UI improvements for …
Browse files Browse the repository at this point in the history
…repeating slides in ajf topbar of Page Slider.

Button toggles in topbar related to not-visible slides are now disabled.
Page slider arrows are now correctly linked to the topbar.
  • Loading branch information
Marco Tozzi authored and mrumbrella committed Mar 6, 2023
1 parent 82c8c14 commit 148b64b
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 70 deletions.
53 changes: 51 additions & 2 deletions projects/core/forms/src/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import {
} from '@angular/core';
import {UntypedFormGroup} from '@angular/forms';
import {Observable, Subscription} from 'rxjs';
import {delayWhen, map, withLatestFrom} from 'rxjs/operators';
import {delayWhen, map, startWith, withLatestFrom} from 'rxjs/operators';

import {AjfFormField} from './field';
import {AjfFormInitStatus, AjfFormRendererService} from './form-renderer';
Expand All @@ -48,6 +48,7 @@ import {AjfNodeGroupInstance} from './interface/nodes-instances/node-group-insta
import {AjfNodeInstance} from './interface/nodes-instances/node-instance';
import {AjfRepeatingSlideInstance} from './interface/slides-instances/repeating-slide-instance';
import {AjfSlideInstance} from './interface/slides-instances/slide-instance';
import {isRepeatingSlideInstance} from './utils/nodes-instances/is-repeating-slide-instance';
import {nodeInstanceCompleteName} from './utils/nodes-instances/node-instance-complete-name';

export interface AjfFormActionEvent {
Expand Down Expand Up @@ -377,7 +378,55 @@ export abstract class AjfFormRenderer implements AfterViewChecked, AfterViewInit
}

scrollToSlide(slide: AjfSlideInstance): void {
this.formSlider.slide({to: slide.position - 1});
let scrollToPos = slide.position - 1;
if (isRepeatingSlideInstance(slide)) {
scrollToPos = scrollToPos - 1 + (slide as AjfRepeatingSlideInstance).reps;
}
this.formSlider.slide({to: scrollToPos});
}

/**
* Return a repeating slide repetition index (eg. 2/5)
* @param slide The repeating slide
* @param currentPage The formslider current page number
* @returns The rep slide index string
*/
getRepeatingSlideRepIndex(
slide: AjfSlideInstance,
currentPage: number,
): Observable<string | null> {
return this.formSlider.pageScrollFinish.pipe(
startWith(null),
map(() => {
if (isRepeatingSlideInstance(slide)) {
const repSlide = slide as AjfRepeatingSlideInstance;
const repsTotal = repSlide.reps;
let currentRep = repsTotal;
if (currentPage + 1 >= slide.position && currentPage + 1 < slide.position + repsTotal) {
currentRep = currentPage + 2 - slide.position;
}
return `(${currentRep}/${repsTotal})`;
}
return null;
}),
);
}

/**
* True if the slide toggle should be checked
* @param slide The repeating slide
* @param currentPage The formslider current page number
* @returns The checked state
*/
isSlideToggleChecked(slide: AjfSlideInstance, currentPage: number): boolean {
let isChecked = slide.position === currentPage + 1;
if (isRepeatingSlideInstance(slide)) {
const repSlide = slide as AjfRepeatingSlideInstance;
isChecked =
currentPage + 1 >= repSlide.position && repSlide.position + repSlide.reps > currentPage + 1;
}

return isChecked;
}

orientationChangeHandler(orientation: AjfPageSliderOrientation): void {
Expand Down
104 changes: 36 additions & 68 deletions projects/material/forms/src/form.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@
<div class="ajf-form-container">
<mat-toolbar *ngIf="!hideTopToolbar && topBar" class="ajf-btn-strip">
<mat-button-toggle-group>
<ng-container *ngFor="let slideInstance of (slides|async); trackBy: trackNodeById">
<ng-container
*ngFor="let slideInstance of (slides|async); let idx = index; trackBy: trackNodeById"
>
<mat-button-toggle
*ngIf="slideInstance.node.label && slideInstance.node.label.length > 0"
class="ajf-topbar-button"
(click)="scrollToSlide(slideInstance)"
[checked]="isSlideToggleChecked(slideInstance, formSlider.currentPage)"
[disabled]="slideInstance.visible === false"
>
{{slideInstance.node.label | transloco}}
{{slideInstance.node.label | transloco}} {{ getRepeatingSlideRepIndex(slideInstance,
formSlider.currentPage)|async}}
<mat-icon *ngIf="!slideInstance.valid" class="ajf-warning">warning</mat-icon>
<mat-icon *ngIf="slideInstance.valid" class="ajf-success">check</mat-icon>
</mat-button-toggle>
Expand All @@ -23,9 +28,7 @@
<ng-content select="[ajfFormTopToolbarButtons]"></ng-content>
<!-- apply a default save button only when ajfFormSaveButton is empty -->
<span *ngIf="!saveDisabled" (click)="onSave($event)">
<span #saveButton
><ng-content select="[ajfFormSaveButton]"></ng-content
></span>
<span #saveButton><ng-content select="[ajfFormSaveButton]"></ng-content></span>
<button
*ngIf="saveButton && saveButton.childNodes && saveButton.childNodes.length === 0"
mat-button
Expand Down Expand Up @@ -53,9 +56,7 @@
<h2>
<span class="ajf-form-header-number"> 1 &rarr; </span>
<span class="ajf-title">
<ng-content
select="[ajfFormStartMessageTitle]"
></ng-content>
<ng-content select="[ajfFormStartMessageTitle]"></ng-content>
</span>
</h2>
</div>
Expand All @@ -67,36 +68,26 @@ <h2>
</div>
</ajf-page-slider-item>
</ng-container>
<ng-container
*ngFor="let slideInstance of curSlides; trackBy:trackNodeById"
>
<ng-container *ngFor="let slideInstance of curSlides; trackBy:trackNodeById">
<!-- non repeating slides -->
<ng-container *ngIf="slideInstance.visible">
<ng-container
*ngIf="!(slideInstance|ajfIsRepeatingSlideInstance)"
>
<ng-container *ngIf="!(slideInstance|ajfIsRepeatingSlideInstance)">
<ajf-page-slider-item>
<div class="ajf-form-page">
<mat-card appearance="outlined">
<mat-card-header>
<div class="ajf-page-slider-item-header">
<h2>
<span class="ajf-form-header-number"
>{{ slideInstance.position + (hasStartMessage |
ajfBoolToInt) }} &rarr;</span
>{{ slideInstance.position + (hasStartMessage | ajfBoolToInt) }}
&rarr;</span
>
<span
[innerHTML]="slideInstance.node.label | transloco"
></span>
<span [innerHTML]="slideInstance.node.label | transloco"></span>
</h2>
<mat-icon
class="ajf-warning"
*ngIf="!slideInstance.valid"
<mat-icon class="ajf-warning" *ngIf="!slideInstance.valid"
>warning</mat-icon
>
<mat-icon
class="ajf-success"
*ngIf="slideInstance.valid"
<mat-icon class="ajf-success" *ngIf="slideInstance.valid"
>check</mat-icon
>
</div>
Expand All @@ -118,9 +109,8 @@ <h2>
item-right
></i>
<p>
{{
((fieldInstance|ajfAsFieldInstance).node.description
|| '') | transloco }}
{{ ((fieldInstance|ajfAsFieldInstance).node.description || '') |
transloco }}
</p>
<label
[attr.id]="fieldInstance.node.name"
Expand All @@ -133,8 +123,8 @@ <h2>
[matTooltip]="hint"
matTooltipPosition="right"
>
{{(fieldInstance|ajfAsFieldInstance).node.hintIcon
|| 'help'}}</mat-icon
{{(fieldInstance|ajfAsFieldInstance).node.hintIcon ||
'help'}}</mat-icon
>
<ajf-field
[instance]="fieldInstance|ajfAsFieldInstance"
Expand All @@ -149,9 +139,7 @@ <h2>
</ajf-page-slider-item>
</ng-container>
<!-- repeating slides -->
<ng-container
*ngIf="(slideInstance|ajfIsRepeatingSlideInstance)"
>
<ng-container *ngIf="(slideInstance|ajfIsRepeatingSlideInstance)">
<ajf-page-slider-item
*ngFor="let curRep of ((slideInstance|ajfAsRepeatingSlideInstance).reps|ajfRange); let idx = index; let lastSlide = last"
>
Expand All @@ -161,30 +149,21 @@ <h2>
<div class="ajf-page-slider-item-header">
<h2>
<span class="ajf-form-header-number"
>{{ slideInstance.position|ajfIncrement:idx +
(hasStartMessage | ajfBoolToInt) }} &rarr;</span
>{{ slideInstance.position|ajfIncrement:idx + (hasStartMessage |
ajfBoolToInt) }} &rarr;</span
>
<span
[innerHTML]="slideInstance.node.label | transloco"
></span>
<span [innerHTML]="slideInstance.node.label | transloco"></span>
</h2>
<mat-icon
class="ajf-warning"
*ngIf="!(slideInstance|ajfValidSlide:idx)"
<mat-icon class="ajf-warning" *ngIf="!(slideInstance|ajfValidSlide:idx)"
>warning</mat-icon
>
<mat-icon
class="ajf-success"
*ngIf="(slideInstance|ajfValidSlide:idx)"
<mat-icon class="ajf-success" *ngIf="(slideInstance|ajfValidSlide:idx)"
>check</mat-icon
>
</div>
</mat-card-header>
<mat-card-content>
<div
*ngIf="lastSlide && !readonly"
class="ajf-group-actions"
>
<div *ngIf="lastSlide && !readonly" class="ajf-group-actions">
<button
(click)="addGroup(slideInstance)"
[disabled]="!(slideInstance|ajfAsRepeatingSlideInstance).canAdd || ((slideInstance|ajfAsRepeatingSlideInstance).node.disableRemoval && !slideInstance.valid)"
Expand Down Expand Up @@ -216,9 +195,8 @@ <h2>
item-right
></i>
<p>
{{
((fieldInstance|ajfAsFieldInstance).node.description
|| '') | transloco }}
{{ ((fieldInstance|ajfAsFieldInstance).node.description || '') |
transloco }}
</p>
<label
[attr.id]="fieldInstance.node.name"
Expand All @@ -230,8 +208,8 @@ <h2>
[matTooltip]="hint"
matTooltipPosition="right"
>
{{(fieldInstance|ajfAsFieldInstance).node.hintIcon
|| 'help'}}</mat-icon
{{(fieldInstance|ajfAsFieldInstance).node.hintIcon ||
'help'}}</mat-icon
>
<ajf-field
[instance]="fieldInstance|ajfAsFieldInstance"
Expand All @@ -247,26 +225,18 @@ <h2>
</ng-container>
</ng-container>
</ng-container>
<ng-container
*ngIf="curSlides && curSlides!.length > 0 && hasEndMessage"
>
<ng-container *ngIf="curSlides && curSlides!.length > 0 && hasEndMessage">
<ajf-page-slider-item>
<div class="ajf-form-page">
<mat-card appearance="outlined">
<mat-card-header>
<div class="ajf-page-slider-item-header">
<h2>
<span
*ngIf="(slidesNum|async) as snum"
class="ajf-form-header-number"
>
{{ snum! + (hasStartMessage | ajfBoolToInt ) + 1 }}
&rarr;
<span *ngIf="(slidesNum|async) as snum" class="ajf-form-header-number">
{{ snum! + (hasStartMessage | ajfBoolToInt ) + 1 }} &rarr;
</span>
<span class="ajf-title">
<ng-content
select="[ajfFormEndMessageTitle]"
></ng-content>
<ng-content select="[ajfFormEndMessageTitle]"></ng-content>
</span>
</h2>
</div>
Expand All @@ -291,9 +261,7 @@ <h2>
</div>
<div class="ajf-info-box ajf-error">
<div class="ajf-title">{{'Errors'|transloco}}</div>
<div class="ajf-content">
{{ errors | async }} / {{ slidesNum|async }}
</div>
<div class="ajf-content">{{ errors | async }} / {{ slidesNum|async }}</div>
</div>
</div>
</div>
Expand Down

0 comments on commit 148b64b

Please sign in to comment.