Skip to content

Instantly share code, notes, and snippets.

@takuya-nakayasu
Last active December 3, 2020 08:24
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 takuya-nakayasu/5cb4cd8ea3014b39341eab18217f24aa to your computer and use it in GitHub Desktop.
Save takuya-nakayasu/5cb4cd8ea3014b39341eab18217f24aa to your computer and use it in GitHub Desktop.
サロゲートペア
import { Component, OnInit } from '@angular/core';
/**
* This is unit test code for StringValidator using karma.
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {
FormBuilder,
FormGroup,
FormsModule,
ReactiveFormsModule
} from '@angular/forms';
import { StringValidator } from './string.validator';
/**
* Component that creates input field for test
*
* @export
* @class RegisterComponent
*/
@Component({
selector: 'app-register',
template: `
<form [formGroup]="form">
<label>surrogatePairMinLength</label>
<input formControlName="surrogatePairMinLength" />
<label>surrogatePairMaxLength</label>
<input formControlName="surrogatePairMaxLength" />
</form>
`
})
export class RegisterComponent implements OnInit {
public form: FormGroup;
constructor(private fb: FormBuilder) {}
/**
* initialize form
*
* @memberof RegisterComponent
*/
public ngOnInit(): void {
this.form = this.fb.group({
surrogatePairMinLength: [null, StringValidator.surrogatePairMinLength(5)],
surrogatePairMaxLength: [null, StringValidator.surrogatePairMaxLength(5)]
});
}
}
/**
* Check if the method checks invalid_inputs and valid_inputs correctly
*
* @param {string} field_name
* @param {RegisterComponent} component
* @param {string[]} valid_inputs
* @param {string[]} invalid_inputs
*/
function assertValues(
field_name: string,
component: RegisterComponent,
valid_inputs: string[],
invalid_inputs: string[]
): void {
const control = component.form.controls[field_name];
for (const invalid of invalid_inputs) {
control.setValue(invalid);
expect(control.valid).toBeFalsy();
}
for (const valid of valid_inputs) {
control.setValue(valid);
expect(control.valid).toBeTruthy();
}
}
it('surrogatePairMinLength', () => {
const valid_inputs = ['12🐍4🏴󠁧󠁢󠁷󠁬󠁳󠁿', '1吉😀家😀🏴󠁧󠁢󠁷󠁬󠁳󠁿😱', '', null];
const invalid_inputs = ['😀😀😀😀', '😀😀 😀', 'abce', '1234'];
assertValues(
'surrogatePairMinLength',
component,
valid_inputs,
invalid_inputs
);
});
it('surrogatePairMaxLength', () => {
const valid_inputs = ['12🐍45', '1吉🏴󠁧󠁢󠁷󠁬󠁳󠁿😀', '', null];
const invalid_inputs = ['😀😀😀😀😀😀', '😀😀 😀😀😀', 'abcedf', '123456'];
assertValues(
'surrogatePairMaxLength',
component,
valid_inputs,
invalid_inputs
);
});
});
import { length } from 'stringz';
import { Injectable } from '@angular/core';
import { AbstractControl, FormControl, ValidatorFn } from '@angular/forms';
/**
* Check if the value is empty
*
* @private
* @param {*} value
* @returns {boolean}
* @memberof NumberValidator
*/
function isEmptyInputValue(value: any): boolean {
// we don't check for string here so it also works with arrays
return value == null || value.length === 0;
}
/**
* Common validator imported from Chat-co robot
*
* @export
* @class StringValidator
*/
@Injectable()
export class StringValidator {
/**
* サロゲートペア文字(絵文字など)も含む最小文字数
*
* @static
* @param {number} minLength
* @return {*} {ValidatorFn}
* @memberof StringValidator
*/
public static surrogatePairMinLength(minLength: number): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
const value = (control.value || '') + '';
if (value === '') {
return null;
}
return length(value) >= minLength
? null
: { minlength: { requiredLength: minLength } };
};
}
/**
* サロゲートペア文字(絵文字など)も含む最大文字数
*
* @static
* @param {number} maxLength
* @return {*} {ValidatorFn}
* @memberof StringValidator
*/
public static surrogatePairMaxLength(maxLength: number): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
const value = (control.value || '') + '';
if (value === '') {
return null;
}
return length(value) <= maxLength
? null
: { maxlength: { requiredLength: maxLength } };
};
}
}
import { length, substring } from 'stringz';
import {
Directive,
ElementRef,
HostListener,
Input,
Renderer2
} from '@angular/core';
/**
* Surrogate pair max length directive.
*
* @export
* @class SurrogatePairMaxLengthDirective
*/
@Directive({
selector: '[appSurrogatePairMaxLength]'
})
export class SurrogatePairMaxLengthDirective {
@Input() public appSurrogatePairMaxLength: number;
constructor(private el: ElementRef, private renderer: Renderer2) {}
/**
* Handles input event.
*
* @param {*} event
* @memberof SurrogatePairMaxLengthDirective
*/
@HostListener('input', ['$event'])
public onChange(event: any): void {
if (length(event.target.value) > this.appSurrogatePairMaxLength) {
this.renderer.setAttribute(
this.el.nativeElement,
'value',
substring(event.target.value, 0, this.appSurrogatePairMaxLength)
);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment