Skip to content

Commit ee99b3d

Browse files
fix(chapter-10): Ensure field gets attached to enclosing form
1 parent b7f33f4 commit ee99b3d

File tree

2 files changed

+23
-17
lines changed

2 files changed

+23
-17
lines changed

1820EN_10_Code/04_field_directive/directive.js

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ angular.module('field-directive', ['input.html', 'textarea.html', 'select.html']
6767

6868
return function postLink(scope, element, attrs) {
6969
// Load up the template for this kind of field, default to the simple input if none given
70-
loadTemplate(attrs.template || 'input.html').then(function(newElement) {
70+
loadTemplate(attrs.template || 'input.html').then(function(templateElement) {
7171
// Set up the scope - the template will have its own scope, which is a child of the directive's scope
7272
var childScope = scope.$new();
7373
// Attach a copy of the message map to the scope
@@ -81,22 +81,17 @@ angular.module('field-directive', ['input.html', 'textarea.html', 'select.html']
8181
// Update the $fieldErrors array when the validity of the field changes
8282
childScope.$watch('$field.$dirty && $field.$error', function(errorList) {
8383
childScope.$fieldErrors = [];
84-
if ( errorList ) {
85-
angular.forEach(errorList, function(invalid, key) {
86-
if ( invalid ) {
87-
childScope.$fieldErrors.push(key);
88-
}
89-
});
90-
}
84+
angular.forEach(errorList, function(invalid, key) {
85+
if ( invalid ) {
86+
childScope.$fieldErrors.push(key);
87+
}
88+
});
9189
}, true);
9290

93-
// Update the label's contents
94-
var labelElement = newElement.find('label');
95-
labelElement.html(labelContent);
9691

9792
// Copy over all left over attributes to the input element
9893
// We can't use interpolation in the template for directives such as ng-model
99-
var inputElement = findInputElement(newElement);
94+
var inputElement = findInputElement(templateElement);
10095
angular.forEach(attrs.$attr, function (original, normalized) {
10196
var value = element.attr(original);
10297
inputElement.attr(original, value);
@@ -107,14 +102,18 @@ angular.module('field-directive', ['input.html', 'textarea.html', 'select.html']
107102
// If we leave it to be interpolated at the next $digest the formController doesn't pick it up
108103
inputElement.attr('name', childScope.$fieldId);
109104
inputElement.attr('id', childScope.$fieldId);
110-
newElement.find('label').attr('for', childScope.$fieldId);
105+
var labelElement = templateElement.find('label');
106+
labelElement.attr('for', childScope.$fieldId);
107+
// Update the label's contents
108+
labelElement.html(labelContent);
109+
110+
// Place our template as a child of the original element.
111+
// This needs to be done before compilation to ensure that it picks up any containing form.
112+
element.append(templateElement);
111113

112114
// We now compile and link our template here in the postLink function
113115
// This allows the ng-model directive on our template's <input> element to access the ngFormController
114-
$compile(newElement)(childScope);
115-
116-
// Place our template as a child of the original element
117-
element.append(newElement);
116+
$compile(templateElement)(childScope);
118117

119118
// Now that our template has been compiled and linked we can access the <input> element's ngModelController
120119
childScope.$field = inputElement.controller('ngModel');

1820EN_10_Code/04_field_directive/directive.spec.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ describe('field directive', function () {
9191
expect(innerScope.$field.$modelValue).toEqual(10);
9292
});
9393

94+
it('adds the ngModelController to an enclosing form', function() {
95+
var form = $compile('<form name="form"><field ng-model="x"></field></form>')(scope);
96+
scope.$digest();
97+
var input = form.find('input');
98+
expect(form.controller('form')[input.prop('name')]).toBe(input.scope().$field);
99+
});
100+
94101
it('updates an array of current error keys as $fieldErrors when the validity of the field changes', function() {
95102
var element = $compile('<field ng-model="x" ng-maxlength="4" required></field>')(scope);
96103
scope.$digest();

0 commit comments

Comments
 (0)