From 6eda36cd4e184e87b5cc88606808fdee8414803b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 1 Dec 2016 00:52:57 -0800 Subject: [PATCH] GUACAMOLE-136: Ensure field template is in DOM prior to invoking controller. --- .../webapp/app/form/directives/formField.js | 6 +-- .../webapp/app/form/services/formService.js | 54 +++++++++++-------- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/guacamole/src/main/webapp/app/form/directives/formField.js b/guacamole/src/main/webapp/app/form/directives/formField.js index 8833be232..2de0d499e 100644 --- a/guacamole/src/main/webapp/app/form/directives/formField.js +++ b/guacamole/src/main/webapp/app/form/directives/formField.js @@ -104,10 +104,8 @@ angular.module('form').directive('guacFormField', [function formField() { // Append field content if (field) { - formService.createFieldElement(field.type, $scope) - .then(function fieldElementCreated(element) { - fieldContent.append(element); - }); + formService.insertFieldElement(fieldContent[0], + field.type, $scope); } }); diff --git a/guacamole/src/main/webapp/app/form/services/formService.js b/guacamole/src/main/webapp/app/form/services/formService.js index 5931d86eb..d76148006 100644 --- a/guacamole/src/main/webapp/app/form/services/formService.js +++ b/guacamole/src/main/webapp/app/form/services/formService.js @@ -201,6 +201,10 @@ angular.module('form').provider('formService', function formServiceProvider() { * model: * The current String value of the field, if any. * + * @param {Element} fieldContainer + * The DOM Element whose contents should be replaced with the + * compiled field template. + * * @param {String} fieldTypeName * The name of the field type defining the nature of the element to be * created. @@ -212,43 +216,51 @@ angular.module('form').provider('formService', function formServiceProvider() { * A Promise which resolves to the compiled Element. If an error occurs * while retrieving the field type, this Promise will be rejected. */ - service.createFieldElement = function createFieldElement(fieldTypeName, scope) { + service.insertFieldElement = function insertFieldElement(fieldContainer, + fieldTypeName, scope) { // Ensure field type is defined var fieldType = provider.fieldTypes[fieldTypeName]; if (!fieldType) return $q.reject(); - // Populate scope using defined controller - if (fieldType.module && fieldType.controller) { - var $controller = angular.injector(['ng', fieldType.module]).get('$controller'); - $controller(fieldType.controller, {'$scope' : scope}); + var templateRequest; + + // Use raw HTML template if provided + if (fieldType.template) { + var deferredTemplate = $q.defer(); + deferredTemplate.resolve(fieldType.template); + templateRequest = deferredTemplate.promise; } + // If no raw HTML template is provided, retrieve template from URL + else + templateRequest = $templateRequest(fieldType.templateUrl); + // Defer compilation of template pending successful retrieval var compiledTemplate = $q.defer(); - // Use raw HTML template if provided - if (fieldType.template) - compiledTemplate.resolve($compile(fieldType.template)(scope)); + // Resolve with compiled HTML upon success + templateRequest.then(function templateRetrieved(html) { - // If no raw HTML template is provided, retrieve template from URL - else { + // Insert template into DOM + fieldContainer.innerHTML = html; - // Attempt to retrieve template HTML - $templateRequest(fieldType.templateUrl) + // Populate scope using defined controller + if (fieldType.module && fieldType.controller) { + var $controller = angular.injector(['ng', fieldType.module]).get('$controller'); + $controller(fieldType.controller, {'$scope' : scope}); + } - // Resolve with compiled HTML upon success - .then(function templateRetrieved(html) { - compiledTemplate.resolve($compile(html)(scope)); - }) + // Compile DOM with populated scope + compiledTemplate.resolve($compile(fieldContainer.childNodes)(scope)); - // Reject on failure - ['catch'](function templateError() { - compiledTemplate.reject(); - }); + }) - } + // Reject on failure + ['catch'](function templateError() { + compiledTemplate.reject(); + }); // Return promise which resolves to the compiled template return compiledTemplate.promise;