Skip to content
This repository was archived by the owner on Jan 5, 2022. It is now read-only.

Commit 1781383

Browse files
authored
Merge pull request #18 from kingcody/idea/help-block-component
Idea: Use help-block component as message outlet
2 parents a26e224 + a1ff236 commit 1781383

File tree

11 files changed

+140
-19
lines changed

11 files changed

+140
-19
lines changed

README.md

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
An Angular module that makes Bootstrap form validation easy.
44

5-
[![Build Status](https://travis-ci.org/third774/ng-bootstrap-form-validation.svg?branch=master)](https://travis-ci.org/third774/ng-bootstrap-form-validation)
5+
[![Build Status](https://travis-ci.org/third774/ng-bootstrap-form-validation.svg?branch=master)](https://travis-ci.org/third774/ng-bootstrap-form-validation)
66
[![Dependencies](https://david-dm.org/third774/ng-bootstrap-form-validation.svg)](https://david-dm.org/third774/ng-bootstrap-form-validation.svg)
77
[![npm downloads](https://img.shields.io/npm/dm/ng-bootstrap-form-validation.svg)](http://npm-stat.com/charts.html?package=ng-bootstrap-form-validation)
88

@@ -30,7 +30,7 @@ import { NgBootstrapFormValidationModule } from 'ng-bootstrap-form-validation';
3030
BrowserModule,
3131
FormsModule,
3232
ReactiveFormsModule,
33-
NgBootstrapFormValidationModule.forRoot()
33+
NgBootstrapFormValidationModule.forRoot()
3434
],
3535
providers: [],
3636
bootstrap: [AppComponent]
@@ -114,6 +114,34 @@ export class BasicExampleComponent implements OnInit {
114114
</div>
115115
```
116116

117+
#### Custom error message placement
118+
119+
`basic-example.component.html`
120+
```html
121+
<div class="row">
122+
<div class="col-md-6 col-md-offset-3">
123+
<form class="form-horizontal" [formGroup]="formGroup" (validSubmit)="onSubmit()">
124+
<div class="form-group">
125+
<label class="control-label col-sm-2">Email</label>
126+
<div class="col-sm-10">
127+
<input type="text" class="form-control" formControlName="Email">
128+
<bfv-messages></bfv-messages>
129+
</div>
130+
</div>
131+
<div class="form-group">
132+
<label class="control-label col-sm-2">Password</label>
133+
<div class="col-sm-10">
134+
<input type="password" class="form-control" formControlName="Password">
135+
<bfv-messages></bfv-messages>
136+
</div>
137+
</div>
138+
<button class="btn btn-default" type="button" (click)="onReset()">Reset</button>
139+
<button class="btn btn-primary pull-right" type="submit">Submit</button>
140+
</form>
141+
</div>
142+
</div>
143+
```
144+
117145
## Custom Error Messages
118146

119147
### Global Custom Errors
@@ -175,7 +203,7 @@ export class AppModule {
175203

176204
In addition to providing custom errors at the top level using the `.forRoot()` method,
177205
you can provide custom error messages to a specific control by binding to the
178-
`customErrorMessages` directive on the `.form-group` element. Modifying the basic
206+
`customErrorMessages` directive on the `.form-group` element. Modifying the basic
179207
example above, we can provide a one time custom error message to a specific `.form-group`. Unlike the global custom error messages, these functions do not need to be individually exported.
180208

181209
`custom-error-example.component.ts`

package-lock.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
"karma-jasmine-html-reporter": "^0.2.2",
6666
"lint-staged": "^4.2.3",
6767
"ng-packagr": "^2.0.0-rc.8",
68+
"ng2-mock-component": "^0.1.0",
6869
"prettier": "^1.7.4",
6970
"protractor": "~5.1.2",
7071
"rimraf": "^2.6.2",

src/lib/Components/form-group-component/form-group-component.html

Lines changed: 0 additions & 2 deletions
This file was deleted.

src/lib/Components/form-group-component/form-group-component.spec.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { async, ComponentFixture, TestBed } from "@angular/core/testing";
22

3+
import { MockComponent } from "ng2-mock-component";
4+
35
import { FormGroupComponent } from "./form-group-component";
46
import { ErrorMessageService } from "../../Services/error-message.service";
57
import { CUSTOM_ERROR_MESSAGES } from "../../Tokens/tokens";
@@ -12,7 +14,13 @@ describe("FormGroupComponent", () => {
1214
beforeEach(
1315
async(() => {
1416
TestBed.configureTestingModule({
15-
declarations: [FormGroupComponent],
17+
declarations: [
18+
FormGroupComponent,
19+
MockComponent({
20+
selector: "bfv-messages",
21+
inputs: ["messages"]
22+
})
23+
],
1624
providers: [
1725
{
1826
provide: ErrorMessageService,

src/lib/Components/form-group-component/form-group-component.ts

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,33 @@
11
import {
22
Component,
33
ContentChildren,
4+
ContentChild,
45
ElementRef,
56
HostBinding,
67
Input,
7-
QueryList
8+
QueryList,
9+
AfterContentInit
810
} from "@angular/core";
911
import { FormControlName } from "@angular/forms";
1012
import { ErrorMessage } from "../../Models/ErrorMessage";
1113
import { ErrorMessageService } from "../../Services/error-message.service";
14+
import { MessagesComponent } from "../messages/messages.component";
1215

1316
@Component({
17+
// tslint:disable:component-selector
1418
selector: ".form-group",
1519
template: `
1620
<ng-content></ng-content>
17-
<span class="help-block" *ngFor="let message of messages">{{message}}</span>
21+
<bfv-messages *ngIf="!messagesBlock" [messages]="messages"></bfv-messages>
1822
`
1923
})
20-
export class FormGroupComponent {
24+
export class FormGroupComponent implements AfterContentInit {
2125
@ContentChildren(FormControlName)
2226
FormControlNames: QueryList<FormControlName>;
2327

2428
@Input() customErrorMessages: ErrorMessage[] = [];
2529

26-
@Input() validationDisabled: boolean = false;
30+
@Input() validationDisabled = false;
2731

2832
@HostBinding("class.has-error")
2933
get hasErrors() {
@@ -42,10 +46,22 @@ export class FormGroupComponent {
4246
);
4347
}
4448

49+
@ContentChild(MessagesComponent) public messagesBlock: MessagesComponent;
50+
51+
public messages: () => string[];
52+
4553
constructor(
4654
private elRef: ElementRef,
4755
private errorMessageService: ErrorMessageService
48-
) {}
56+
) {
57+
this.messages = () => this.getMessages();
58+
}
59+
60+
ngAfterContentInit() {
61+
if (this.messagesBlock) {
62+
this.messagesBlock.messages = this.messages;
63+
}
64+
}
4965

5066
get label() {
5167
const label = this.elRef.nativeElement.querySelector("label");
@@ -63,13 +79,17 @@ export class FormGroupComponent {
6379
];
6480
}
6581

66-
get messages(): string[] {
82+
private getMessages(): string[] {
6783
const messages = [];
68-
if (!this.isDirtyAndTouched || this.validationDisabled) return messages;
84+
if (!this.isDirtyAndTouched || this.validationDisabled) {
85+
return messages;
86+
}
6987
this.FormControlNames.filter(c => !c.valid).forEach(control => {
7088
Object.keys(control.errors).forEach(key => {
71-
const error = this.errorMessages.find(error => error.error === key);
72-
if (!error) return;
89+
const error = this.errorMessages.find(err => err.error === key);
90+
if (!error) {
91+
return;
92+
}
7393
messages.push(error.format(this.label, control.errors[key]));
7494
});
7595
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { async, ComponentFixture, TestBed } from "@angular/core/testing";
2+
import { By } from "@angular/platform-browser";
3+
4+
import { MessagesComponent } from "./messages.component";
5+
6+
describe("MessagesComponent", () => {
7+
const messages = ["message one", "message two"];
8+
const getMessages = () => messages;
9+
let component: MessagesComponent;
10+
let fixture: ComponentFixture<MessagesComponent>;
11+
12+
beforeEach(
13+
async(() => {
14+
TestBed.configureTestingModule({
15+
declarations: [MessagesComponent]
16+
}).compileComponents();
17+
})
18+
);
19+
20+
beforeEach(() => {
21+
fixture = TestBed.createComponent(MessagesComponent);
22+
component = fixture.componentInstance;
23+
component.messages = getMessages;
24+
fixture.detectChanges();
25+
});
26+
27+
it("should create a span element for every message", () => {
28+
const spans = fixture.debugElement.queryAll(By.css("span"));
29+
expect(spans.length).toEqual(messages.length);
30+
});
31+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Component, Input } from "@angular/core";
2+
3+
@Component({
4+
selector: "bfv-messages",
5+
template: `
6+
<span class="help-block" *ngFor="let message of messages()">{{message}}</span>
7+
`
8+
})
9+
export class MessagesComponent {
10+
@Input() public messages = () => [];
11+
12+
constructor() {}
13+
}

src/lib/ng-bootstrap-form-validation.module.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,20 @@ import { CommonModule } from "@angular/common";
22
import { NgModule, ModuleWithProviders } from "@angular/core";
33
import { FormValidationDirective } from "./Directives/form-validation.directive";
44
import { FormGroupComponent } from "./Components/form-group-component/form-group-component";
5+
import { MessagesComponent } from "./Components/messages/messages.component";
56
import { ErrorMessageService } from "./Services/error-message.service";
67
import { ErrorMessage } from "./Models/ErrorMessage";
78
import { CUSTOM_ERROR_MESSAGES } from "./Tokens/tokens";
89

910
@NgModule({
10-
declarations: [FormValidationDirective, FormGroupComponent],
11+
declarations: [
12+
FormValidationDirective,
13+
FormGroupComponent,
14+
MessagesComponent
15+
],
1116
imports: [CommonModule],
1217
providers: [ErrorMessageService],
13-
exports: [FormValidationDirective, FormGroupComponent]
18+
exports: [FormValidationDirective, FormGroupComponent, MessagesComponent]
1419
})
1520
export class NgBootstrapFormValidationModule {
1621
static forRoot(customErrorMessages?: ErrorMessage[]): ModuleWithProviders {

src/lib/public_api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ export {
99
export {
1010
FormGroupComponent
1111
} from "./Components/form-group-component/form-group-component";
12+
export { MessagesComponent } from "./Components/messages/messages.component";

0 commit comments

Comments
 (0)