Browse Source

Better layout for checkboxes.

pull/498/head
Sebastian 6 years ago
parent
commit
6220cd3ec4
  1. 4
      frontend/app/framework/angular/forms/editors/checkbox-group.component.html
  2. 13
      frontend/app/framework/angular/forms/editors/checkbox-group.component.scss
  3. 99
      frontend/app/framework/angular/forms/editors/checkbox-group.component.ts

4
frontend/app/framework/angular/forms/editors/checkbox-group.component.html

@ -1,4 +1,5 @@
<div class="form-check" *ngFor="let value of values">
<div #container (sqxResized)="updateContainerWidth($event.width)">
<div class="form-check" [class.form-check-block]="!isSingleLine" [class.form-check-inline]="isSingleLine" *ngFor="let value of values">
<input type="checkbox" class="form-check-input" id="{{controlId}}{{value}}"
(blur)="callTouched()"
(change)="check($event.target.checked, value)"
@ -6,4 +7,5 @@
[disabled]="snapshot.isDisabled">
<label class="form-check-label" for="{{controlId}}{{value}}">{{value}}</label>
</div>
</div>

13
frontend/app/framework/angular/forms/editors/checkbox-group.component.scss

@ -1,13 +1,10 @@
.form-check {
display: block;
.form-check-block {
& {
margin-bottom: .5rem;
margin-left: 0;
}
}
.form-check-input {
.form-check-input {
margin-top: .4rem;
}
label {
min-width: 5rem;
}
}

99
frontend/app/framework/angular/forms/editors/checkbox-group.component.ts

@ -7,7 +7,7 @@
// tslint:disable: readonly-array
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, forwardRef, Input } from '@angular/core';
import { AfterViewChecked, AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, Input, OnChanges, ViewChild } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import {
@ -20,6 +20,8 @@ export const SQX_CHECKBOX_GROUP_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CheckboxGroupComponent), multi: true
};
let CACHED_FONT: string;
interface State {
// The checked values.
checkedValues: ReadonlyArray<string>;
@ -34,9 +36,18 @@ interface State {
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CheckboxGroupComponent extends StatefulControlComponent<State, string[]> {
export class CheckboxGroupComponent extends StatefulControlComponent<State, string[]> implements AfterViewInit, AfterViewChecked, OnChanges {
private childrenWidth = 0;
private containerWidth = 0;
private labelsMeasured = false;
public readonly controlId = MathHelper.guid();
public isSingleLine = false;
@ViewChild('container', { static: false })
public containerElement: ElementRef<HTMLDivElement>;
@Input()
public values: ReadonlyArray<string> = [];
@ -46,6 +57,88 @@ export class CheckboxGroupComponent extends StatefulControlComponent<State, stri
});
}
public ngAfterViewInit() {
this.calculateWidth();
}
public ngAfterViewChecked() {
this.calculateWidth();
}
public ngOnChanges() {
this.labelsMeasured = false;
this.calculateWidth();
}
public updateContainerWidth(width: number) {
this.containerWidth = width;
this.calculateSingleLine();
}
private calculateWidth() {
this.calculateStyle();
if (this.labelsMeasured) {
return;
}
if (!CACHED_FONT ||
!this.containerElement ||
!this.containerElement.nativeElement) {
return;
}
if (!canvas) {
canvas = document.createElement('canvas');
}
if (canvas) {
const ctx = canvas.getContext('2d');
if (ctx) {
ctx.font = CACHED_FONT;
let width = 0;
for (let text of this.values) {
width += 30;
width += ctx.measureText(text).width;
}
this.childrenWidth = width;
this.calculateSingleLine();
this.labelsMeasured = true;
}
}
}
private calculateSingleLine() {
this.isSingleLine = this.childrenWidth < this.containerWidth;
}
private calculateStyle() {
if (CACHED_FONT ||
!this.containerElement ||
!this.containerElement.nativeElement) {
return;
}
const style = window.getComputedStyle(this.containerElement.nativeElement);
const fontSize = style.getPropertyValue('font-size');
const fontFamily = style.getPropertyValue('font-family');
if (!fontSize || !fontFamily) {
return;
}
CACHED_FONT = `${fontSize} ${fontFamily}`;
}
public writeValue(obj: any) {
const checkedValues = Types.isArrayOfString(obj) ? obj.filter(x => this.values.indexOf(x) >= 0) : [];
@ -70,3 +163,5 @@ export class CheckboxGroupComponent extends StatefulControlComponent<State, stri
return this.snapshot.checkedValues.indexOf(value) >= 0;
}
}
let canvas: HTMLCanvasElement | null = null;
Loading…
Cancel
Save