Skip to content

Instantly share code, notes, and snippets.

@blemaire
Last active May 13, 2019 09:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save blemaire/3b41f9986637a6f3c5d02bdcb6915779 to your computer and use it in GitHub Desktop.
Save blemaire/3b41f9986637a6f3c5d02bdcb6915779 to your computer and use it in GitHub Desktop.
Example responsibe form

Explanations of the issue

This GIST was created to explain an issue we are going to encounter when we start using responsive forms. In short, the current spacing between rows and columns is different (40px between columns and 26px between rows) When switching from row layout to column layout (on small screens) the gaps will not be consistent between each form controls.

the gap between the elements of the same row will be correct (26px) but the gap between each row will be (26px) resulting in a very strange looking form.

The current api of the layout library (@angular/flex-layout) would mean we'd have to write something like this:

<div fxLayout="column">
  <div 
     fxLayout="row" 
     fxLayout.xs="column" 
     fxLayouGap="26px" 
     fxLayouGap.XS="40px"
   >
    <div fxLayout="row">
      <span>Row 1 - Column 1</span>
      <span>Row 1 - Column 2</span>
    </div>
  </div>
</div>

2 main issues are :

  • We have to know what sizes to use (26px and 40px)
  • the breakpoint is fixed to XS screens (this is configurable but this is only impacted by the screen size and not the container's width)

Proposed solution:

The solution presented in this GIST is just an idea of what I think should be possible to do to ease the responsiveness of forms.

It seems to solve most issues I could think of:

  • the layout must change when the container width changes (the screen size is not enough for us)
  • the size of the gaps must be predefined values to ensure consistent spacing between forms
  • the user should not need to remember those value
  • the gap between columns must automaticaly change when switching from row to column layout

setup:

Note checkout the component files below before reading on.

Line 1 of the template:

<div #contentToResize *nwaForm="let formLayout; from containerWidth$; columnCount = 2; breakAt = 600">
  
  <!-- form content goes here -->
  
  <nwa-resize-sensor
    (resize)="resizeRequest.next($event)"
    [template]="contentToResize"
  ></nwa-resize-sensor>
</div>
  • #contentToResize is given to the resize sensor to know which element's size to be watched for size changes (this could be removed as long as the resize sensor is the direct child of the form)
  • let formLayout is the local variable in which the form sizes and direction will be available (they update as the form changes size)
  • from containerWidth$ is the observable that contains updates when the form changes width (visible in the controller)
  • columnCount = 2 is necessary to work out when to break from 'row' to 'column' layout
  • breakAt = 600 is used to tell when to switch from row to column layout (could have a default value)

Usage in the form

<div 
 [fxLayout]="formLayout.direction$ | async" 
 [fxLayoutGap]="formLayout.columGap$ | async"
>
  • [fxLayout]="formLayout.direction$ | async" the observable that switches from 'row' to 'column' when we reach the breakpoint (600px in this example)
  • [fxLayoutGap]="formLayout.columGap$ | async" The observable that switches the gap size when changing from 'row' to 'column' layout
  • [fxLayoutGap]="formLayout.rowGap$ | async" The observable contains the gap to put between each row (this should always be 40px but keeping it as an observable makes it more consistent with the other variables and more flexible)
class ExampleFormComponent implements OnInit {
/**
* The width of the container
*/
private containerWidthSubject = new BehaviorSubject<number>(1000);
public containerWidth$ = this.containerWidthSubject.asObservable();
/**
* The observable that gets fired when the size of the sensor changes
*/
public resizeRequest = new Subject<any>();
ngOnInit() {
this.resizeRequest.subscribe((response: NwaResizeSensorEvent) => {
this.containerWidthSubject.next(response.newWidth);
});
}
}
<div *nwaForm="let formLayout; from containerWidth$; columnCount = 2" #contentToResize>
<div
[fxLayout]="formLayout.direction$ | async"
[fxLayoutGap]="formLayout.rowGap$ | async"
>
<div
fxLayout"row"
[fxLayoutFap]="formLayout.columGap$ | async"
>
<span>Row 1 - Column 1</span>
<span>Row 1 - Column 2</span>
</div>
<div
fxLayout"row"
[fxLayoutFap]="formLayout.columGap$ | async"
>
<span>Row 2 - Column 1</span>
</div>
</div>
<nwa-resize-sensor
(resize)="resizeRequest.next($event)"
[template]="contentToResize"
></nwa-resize-sensor>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment