Two components remain to remove the bloat from the form field components. Assume the form fields consist of three elements, a label, the material input, and the validation message.
The components required to create the form field repeat, adding to the bloat. The goal remains to not repeat yourself. Covering 99% of the use cases and having a consistent form field that meets expectations of the user, wrapping the form field, label, and validation message directive from part 1 into a reusable component is the goal.
- Create a Reusable Material Form Field Component
- Create a Reusable Form
- Show the Slimmer Login Form Component
1. Create a Reusable Material Form Field Component
The component will consist of three input properties.
label - The label displays as the mat-label in the form field. It also serves as the fieldName for the validationDisplayDirective created in part 1.
control - The form field control of the material input
appearance - This controls the appearance form field per Angular Material's option of the mat-form-field .
Angular Material's form field has issues with content projection when material input is entered in the ng-content area. The property
formFieldControl defines as a
MaterialFormFiedlControl<any> so the control may be overridden.
matFormField property grabs the Material Form Field.
ngOnInit helps define the
_control property of the
matFormField, suppressing errors complaining of missing material inputs.
Content projection slots exist allowing form field prefixes and suffixes for icons. The
mat-label component contains the
label property. The
ng-content projects the material component used in the containing form. Finally,
mat-error contains a span field with the
[appValidationDisplay] directive that watches the control for different validation error messages.
Below, notice the markup removed from the form making it easier to read.
Ah, that's nice. It's slimmer than it's predecessor bloating the mark up with validation messages and labels.
Now, if multiple forms need to support these CRUD type applications a consistent experience for the form should also be implemented.
2. Create a Reusable Form
The form exists for the purpose of saving the data and cancelling. The buttons should have a consistent style and emit different actions up to the consuming component. Again, no one wants to keep re-writing this markup and for behavior and style to differ between forms.
From the form component, the consuming component listens for events
cancel. The consuming component handles these actions as the orchestrator knowing which services to call.
The consuming component's responsibility controls the data pushed into the form component including button disabling, button text,
3. Show The Slimmer Login Component
Lets put the pieces together of the form, form fields, and validation messages. In this instance, lets create a User Login Form.
Two form fields with a couple of attributes per each field improves the readability of the markup. The form requires more attributes but provides a uniform user experince. Best yet, reusing the component for the multiple input use cases makes updates across multiple forms easy.
loginFromGroup implements the email and password
FormControls. They include any needed validations that the
ValidationDisplayDirective shows when the control possesses a matching error key in the
VALIDATION_MESSAGES map of validation key/error message.
Creating a consistent experience for developers and the end user should remain priority. The form field encompasses a lot of markup bloat including a label, suffix, prefix, and validation messages. These can be slimmed down in the FormFieldComponent which handles quite a bit of our use cases in Angular Material forms.