Skip to content
This repository was archived by the owner on Oct 7, 2020. It is now read-only.

Commit e97d755

Browse files
authored
fix(text-field): Respect custom validity property (#1531)
Also, fixes Edge compatibility reported in #1522 Closes #1523 Closes #1522
1 parent 1168629 commit e97d755

File tree

3 files changed

+74
-69
lines changed

3 files changed

+74
-69
lines changed

demos/components/textfield-demo/textfield-demo.html

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -249,18 +249,21 @@ <h3 class="demo-content__headline">Text Field - FormControl</h3>
249249
<button mdc-button (click)="demoformInput.useNativeValidation = !demoformInput.useNativeValidation">Use native validation: {{demoformInput.useNativeValidation ? 'On' : 'Off'}}</button>
250250
<button mdc-button (click)="alternateColors(demoformInput)">Alternate Colors</button>
251251
</div>
252-
<form [formGroup]="demoForm" id="demoForm" (ngSubmit)="submitForm()">
253-
<mdc-text-field #demoformInput formControlName="userName" label="Username" outlined [readonly]="readonly" [helperText]="demoformHelper" required minlength="3"></mdc-text-field>
254-
<mdc-text-field-helper-text #demoformHelper="mdcHelperText" validation>
255-
<span *ngIf="demoForm.controls['userName'].errors?.required">Username is required</span>
256-
<span *ngIf="demoForm.controls['userName'].errors?.minlength">Username is not long enough</span>
257-
</mdc-text-field-helper-text>
252+
<form [formGroup]="demoForm" id="demoForm">
253+
<mdc-form-field>
254+
<mdc-text-field #demoformInput formControlName="username" label="Username" outlined [helperText]="demoformHelper" required minlength="3"></mdc-text-field>
255+
<mdc-text-field-helper-text #demoformHelper="mdcHelperText" validation>
256+
<span *ngIf="demoForm.controls['username'].errors?.required">Username is required</span>
257+
<span *ngIf="demoForm.controls['username'].errors?.minlength">Username is not long enough</span>
258+
</mdc-text-field-helper-text>
259+
</mdc-form-field>
258260
</form>
259261
<div class="demo-layout__row">
260262
<button mdc-button type="submit" [disabled]="!demoForm.valid" form="demoForm">Submit</button>
261263
<button mdc-button (click)="demoForm.reset()">Reset</button>
262-
<button mdc-button (click)="demoForm.controls['userName'].setValue('test')">Set Value</button>
264+
<button mdc-button (click)="demoForm.controls['username'].setValue('test')">Set Value</button>
263265
</div>
266+
<p>Control Valid: {{demoForm.controls['username'].valid}}</p>
264267
<p>Dirty: {{ demoForm.dirty }}</p>
265268
<p>Valid: {{ demoForm.valid }}</p>
266269
<p>Pristine: {{ demoForm.pristine }}</p>
@@ -277,16 +280,18 @@ <h3 class="demo-content__headline">Text Field - Numeric with ngModel Form</h3>
277280
<button mdc-button (click)="demoweight.required = !demoweight.required">Required: {{demoweight.required ? 'On' : 'Off'}}</button>
278281
<button mdc-button (click)="alternateColors(demoweight)">Alternate Colors</button>
279282
</div>
280-
<form #demoWeightForm="ngForm" id="demoWeightForm" (ngSubmit)="submitWeightForm(demoWeightForm)">
281-
<mdc-text-field #demoweight type="number" name="demoweight" label="Weight" ngModel #demoWeightModel="ngModel"
282-
required [helperText]="weightHelper"></mdc-text-field>
283-
<mdc-text-field-helper-text #weightHelper="mdcHelperText" validation>
284-
<span *ngIf="!demoweight?.value">Weight is required</span>
285-
</mdc-text-field-helper-text>
283+
<form #demoWeightForm="ngForm" id="demoWeightForm">
284+
<mdc-form-field>
285+
<mdc-text-field #demoweight type="number" name="demoweight" label="Weight" ngModel #demoWeightModel="ngModel"
286+
required [helperText]="weightHelper"></mdc-text-field>
287+
<mdc-text-field-helper-text #weightHelper="mdcHelperText" validation>
288+
<span *ngIf="!demoweight?.value">Weight is required</span>
289+
</mdc-text-field-helper-text>
290+
</mdc-form-field>
286291
</form>
287292
<div class="demo-layout__row">
288-
<button mdc-button type="submit" form="demoWeightForm">Submit</button>
289-
<button mdc-button (click)="resetWeightModel(demoWeightForm)">Reset</button>
293+
<button mdc-button type="submit" [disabled]="!demoWeightForm.valid" form="demoWeightForm">Submit</button>
294+
<button mdc-button (click)="demoWeightForm.reset()">Reset</button>
290295
</div>
291296
<p>Dirty: {{ demoWeightModel.dirty }}</p>
292297
<p>Valid: {{ demoWeightForm.valid }}</p>
@@ -317,10 +322,12 @@ <h3 class="demo-content__headline">Leading and Trailing Icons</h3>
317322
<div class="demo-layout__row">
318323
<button mdc-button (click)="bothIcons.outlined = !bothIcons.outlined">Outlined: {{bothIcons.outlined ? 'On' : 'Off'}}</button>
319324
</div>
320-
<mdc-text-field autocomplete="tel" type="tel" #bothIcons label="Phone number">
321-
<mdc-icon mdcTextFieldIcon leading>phone</mdc-icon>
322-
<mdc-icon mdcTextFieldIcon trailing>event</mdc-icon>
323-
</mdc-text-field>
325+
<mdc-form-field>
326+
<mdc-text-field autocomplete="tel" type="tel" #bothIcons label="Phone number">
327+
<mdc-icon mdcTextFieldIcon leading>phone</mdc-icon>
328+
<mdc-icon mdcTextFieldIcon trailing>event</mdc-icon>
329+
</mdc-text-field>
330+
</mdc-form-field>
324331
</div>
325332

326333
<div class="demo-content">
@@ -356,9 +363,7 @@ <h3 class="demo-content__headline">Examples</h3>
356363
<div class="demo-content">
357364
<h3 class="demo-content__headline">Numeric with ngModel</h3>
358365
<mdc-text-field type="number" label="Distance" [(ngModel)]="waypoint.dt"></mdc-text-field>
359-
<div class="demo-layout__row">
360-
<button mdc-button (click)="submitNumeric()">Submit</button>
361-
</div>
366+
<p>Model: {{waypoint | json}}</p>
362367
</div>
363368

364369
<div class="demo-content">
@@ -370,10 +375,18 @@ <h3 class="demo-content__headline">Prefilled via ngModel</h3>
370375
<div class="demo-content">
371376
<h3 class="demo-content__headline">Date / Time / Color / Password</h3>
372377
<div class="demo-layout__row">
373-
<mdc-text-field type="date" label="Birthday" outlined></mdc-text-field>
374-
<mdc-text-field type="time" label="Time" outlined></mdc-text-field>
375-
<mdc-text-field type="password" label="Password" required outlined></mdc-text-field>
376-
<mdc-text-field type="color" label="Color" style="width: 6rem" outlined></mdc-text-field>
378+
<mdc-form-field>
379+
<mdc-text-field type="date" label="Birthday" outlined></mdc-text-field>
380+
</mdc-form-field>
381+
<mdc-form-field>
382+
<mdc-text-field type="time" label="Time" outlined></mdc-text-field>
383+
</mdc-form-field>
384+
<mdc-form-field>
385+
<mdc-text-field type="password" label="Password" required outlined></mdc-text-field>
386+
</mdc-form-field>
387+
<mdc-form-field>
388+
<mdc-text-field type="color" label="Color" style="width: 6rem" outlined></mdc-text-field>
389+
</mdc-form-field>
377390
</div>
378391
</div>
379392

demos/components/textfield-demo/textfield-demo.ts

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Component } from '@angular/core';
2-
import { FormControl, FormGroup, NgForm, Validators } from '@angular/forms';
2+
import { FormControl, FormGroup, Validators } from '@angular/forms';
33

44
import { MdcTextField } from '@angular-mdc/web';
55

@@ -12,12 +12,8 @@ class Directions {
1212
})
1313
export class TextFieldDemo {
1414
demoForm = new FormGroup({
15-
userName: new FormControl(
16-
{ value: '', disabled: false },
17-
[
18-
Validators.required,
19-
Validators.minLength(3)
20-
])
15+
username: new FormControl(
16+
{ value: '', disabled: false }, [Validators.required])
2117
});
2218

2319
waypoint = new Directions();
@@ -26,26 +22,6 @@ export class TextFieldDemo {
2622
username: string;
2723
prefilledText: string = 'Prefilled';
2824

29-
submitForm() {
30-
if (!this.demoForm.valid) {
31-
return;
32-
}
33-
}
34-
35-
submitNumeric() {
36-
console.log(this.waypoint);
37-
}
38-
39-
submitWeightForm(f: NgForm) {
40-
if (!f.valid) {
41-
return;
42-
}
43-
}
44-
45-
resetWeightModel(f: NgForm) {
46-
f.reset();
47-
}
48-
4925
alternateColors(input: MdcTextField) {
5026
if (!input.textarea) {
5127
const demoTextField = 'demo-text-field-custom-colors';

packages/textfield/text-field.ts

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,10 @@ export class MdcTextField implements AfterContentInit, OnDestroy, ControlValueAc
147147
get required(): boolean { return this._required; }
148148
set required(value: boolean) {
149149
this._required = toBoolean(value);
150-
this._changeDetectorRef.markForCheck();
151-
this._handleValidationAttributeChange();
150+
if (this._initialized) {
151+
this._changeDetectorRef.markForCheck();
152+
this._handleValidationAttributeChange();
153+
}
152154
}
153155
private _required: boolean;
154156

@@ -182,6 +184,15 @@ export class MdcTextField implements AfterContentInit, OnDestroy, ControlValueAc
182184
}
183185
private _helperText: MdcTextFieldHelperText;
184186

187+
/** Sets the Text Field valid or invalid. */
188+
@Input()
189+
get valid(): boolean { return this._valid; }
190+
set valid(value: boolean) {
191+
this._valid = toBoolean(value);
192+
this._foundation.setValid(this._valid);
193+
}
194+
private _valid: boolean;
195+
185196
/** Enables or disables the use of native validation. Use this for custom validation. */
186197
@Input()
187198
get useNativeValidation(): boolean { return this._useNativeValidation; }
@@ -198,15 +209,6 @@ export class MdcTextField implements AfterContentInit, OnDestroy, ControlValueAc
198209
}
199210
private _value: any;
200211

201-
/** Sets the Text Field valid or invalid. */
202-
@Input()
203-
get valid(): boolean { return this._valid; }
204-
set valid(value: boolean) {
205-
this._valid = toBoolean(value);
206-
this._foundation.setValid(this._valid);
207-
}
208-
private _valid: boolean;
209-
210212
@Output() readonly change = new EventEmitter<any>();
211213
@Output() readonly blur = new EventEmitter<any>();
212214

@@ -251,7 +253,7 @@ export class MdcTextField implements AfterContentInit, OnDestroy, ControlValueAc
251253
value: this._value,
252254
disabled: this._input.nativeElement.disabled,
253255
validity: {
254-
valid: this.useNativeValidation ? this._input.nativeElement.validity.valid : !!this._valid,
256+
valid: this._valid ? this._valid : this._input.nativeElement.validity.valid,
255257
badInput: this._input.nativeElement.validity.badInput
256258
}
257259
};
@@ -309,7 +311,6 @@ export class MdcTextField implements AfterContentInit, OnDestroy, ControlValueAc
309311
setDisabled(disabled: boolean): void,
310312
setValid(isValid: boolean): void,
311313
setValue(value: any): void,
312-
isValid(): boolean,
313314
readonly shouldFloat: boolean,
314315
notchOutline(openNotch: boolean): void,
315316
setUseNativeValidation(useNativeValidation: boolean): void,
@@ -348,9 +349,9 @@ export class MdcTextField implements AfterContentInit, OnDestroy, ControlValueAc
348349

349350
this._initRipple();
350351
this._foundation.init();
351-
this._initialized = true;
352+
this._checkCustomValidity();
352353

353-
this._changeDetectorRef.markForCheck();
354+
this._initialized = true;
354355
}
355356

356357
onTextFieldInteraction(): void {
@@ -456,8 +457,23 @@ export class MdcTextField implements AfterContentInit, OnDestroy, ControlValueAc
456457
});
457458
}
458459

460+
private _checkCustomValidity(): void {
461+
Promise.resolve().then(() => {
462+
if (this._valid !== undefined) {
463+
this._foundation.setValid(this._valid);
464+
}
465+
});
466+
}
467+
459468
private _handleValidationAttributeChange(): void {
460-
this._foundation.handleValidationAttributeChange(this._getInputElement().getAttributeNames());
469+
Promise.resolve().then(() => {
470+
const attributes = this._getInputElement().attributes;
471+
const result = new Array(length);
472+
for (let i = 0; i < attributes.length; i++) {
473+
result[i] = attributes[i].name;
474+
}
475+
this._foundation.handleValidationAttributeChange(result);
476+
});
461477
}
462478

463479
private _initRipple(): void {

0 commit comments

Comments
 (0)