From 04844e2a8d974160f1742b884c578368a6a313c8 Mon Sep 17 00:00:00 2001 From: Pawel Kozlowski Date: Sat, 8 Sep 2012 17:38:08 +0200 Subject: [PATCH 1/3] Initial version of the ui-input directive --- modules/directives/input/input.js | 101 ++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 modules/directives/input/input.js diff --git a/modules/directives/input/input.js b/modules/directives/input/input.js new file mode 100644 index 0000000..9a7b487 --- /dev/null +++ b/modules/directives/input/input.js @@ -0,0 +1,101 @@ +angular.module('ui.directives', ['ui.config']) + .factory('InputHelper', ['$compile', '$http', '$templateCache', 'ui.config', function ($compile, $http, $templateCache, uiConfig) { + + uiConfig.uiinput = uiConfig.uiinput || {}; + + var idUid = ['0', '0', '0']; + var nameUid = ['0', '0', '0']; + + /* + Copyright (c) 2010-2012 Google, Inc. http://angularjs.org + This function is slightly modified version of the nextUid() function found in AngularJS code base + */ + function nextUid(uid) { + var index = uid.length; + var digit; + + while (index) { + index--; + digit = uid[index].charCodeAt(0); + if (digit == 57 /*'9'*/) { + uid[index] = 'A'; + return uid.join(''); + } + if (digit == 90 /*'Z'*/) { + uid[index] = '0'; + } else { + uid[index] = String.fromCharCode(digit + 1); + return uid.join(''); + } + } + uid.unshift('0'); + return uid.join(''); + } + + /* + Copyright (c) 2010-2012 Google, Inc. http://angularjs.org + This function is slightly modified version of the snake_case() function found in AngularJS code base + */ + function snake_case(name, separator) { + return name.replace(/[A-Z]/g, function (letter, pos) { + return (pos ? separator : '') + letter.toLowerCase(); + }); + } + + var internalAttrs = ['family', 'kind', 'validation']; + + return { + restrict:'E', + priority:10000, + terminal:true, + compile:function compile(tElement, tAttrs, transclude) { + + var control = { + id:tAttrs.id || 'id' + nextUid(idUid) + }; + + return function (scope, element, attrs) { + + var childScope = scope.$new(); + var tplFamily = tAttrs.family || uiConfig.uiinput.family; + var tplKind = tAttrs.kind || uiConfig.uiinput.kind; + + //infer a field type from template's tag name (can be one of ui-input, ui-select, ui-textarea) + var targetTagName = tElement[0].tagName.substring(3).toLowerCase(); + + $http.get(targetTagName + '.' + tplFamily + '.' + tplKind + '.html', {cache:$templateCache}).success(function (response) { + + element.html(response); + + var inputEl = angular.element(element.find(targetTagName)[0]); + angular.forEach(tAttrs, function (value, key) { + if (key.charAt(0) !== '$') { + if (key.indexOf('input') === 0) { + control[key.charAt(5).toLowerCase() + key.substr(6)] = value; + } else { + inputEl.attr(snake_case(key, '-'), value); + } + } + }); + + //prepare validation messages + control.validation = angular.extend({}, uiConfig.uiinput.validation, scope.$eval(tAttrs.validation)); + + //expose model to a field's template + childScope.$control = control; + $compile(element.contents())(childScope); + childScope.$field = inputEl.controller('ngModel'); + }); + }; + } + }; +}]) + .directive('uiInput', ['InputHelper', function (InputHelper) { + return InputHelper; +}]) + .directive('uiTextarea', ['InputHelper', function (InputHelper) { + return InputHelper; +}]) + .directive('uiSelect', ['InputHelper', function (InputHelper) { + return InputHelper; +}]); \ No newline at end of file From 2912b8ff536d0011d1c4491058383a5a03723bb1 Mon Sep 17 00:00:00 2001 From: Dean Sofer Date: Wed, 31 Oct 2012 18:13:29 -0700 Subject: [PATCH 2/3] Made some changes in line with comments For some reason $compile() is throwing an error Stubbed out uiForm dependency but need help creating the directive --- modules/directives/input/input.js | 53 ++++++++++--------------------- 1 file changed, 17 insertions(+), 36 deletions(-) diff --git a/modules/directives/input/input.js b/modules/directives/input/input.js index 9a7b487..9561f74 100644 --- a/modules/directives/input/input.js +++ b/modules/directives/input/input.js @@ -1,7 +1,7 @@ -angular.module('ui.directives', ['ui.config']) - .factory('InputHelper', ['$compile', '$http', '$templateCache', 'ui.config', function ($compile, $http, $templateCache, uiConfig) { +angular.module('ui.directives') + .directive('uiInput', ['$compile', '$http', '$templateCache', 'ui.config', function ($compile, $http, $templateCache, uiConfig) { - uiConfig.uiinput = uiConfig.uiinput || {}; + uiConfig.input = uiConfig.input || {}; var idUid = ['0', '0', '0']; var nameUid = ['0', '0', '0']; @@ -42,60 +42,41 @@ angular.module('ui.directives', ['ui.config']) }); } - var internalAttrs = ['family', 'kind', 'validation']; - return { - restrict:'E', + restrict:'EA', priority:10000, terminal:true, - compile:function compile(tElement, tAttrs, transclude) { + scope:true, + require:'?uiForm', + compile:function compile(tElement, tAttrs, transclude, uiForm) { - var control = { - id:tAttrs.id || 'id' + nextUid(idUid) + var model = tAttrs.ngModel, input = { + id:tAttrs.id || 'input' + nextUid(idUid) }; return function (scope, element, attrs) { - var childScope = scope.$new(); - var tplFamily = tAttrs.family || uiConfig.uiinput.family; - var tplKind = tAttrs.kind || uiConfig.uiinput.kind; - //infer a field type from template's tag name (can be one of ui-input, ui-select, ui-textarea) - var targetTagName = tElement[0].tagName.substring(3).toLowerCase(); - - $http.get(targetTagName + '.' + tplFamily + '.' + tplKind + '.html', {cache:$templateCache}).success(function (response) { + $http.get(scope.$eval(attrs.src), {cache:$templateCache}).success(function (response) { element.html(response); - var inputEl = angular.element(element.find(targetTagName)[0]); + var inputEl = element.find('[ng-transclude]'); angular.forEach(tAttrs, function (value, key) { - if (key.charAt(0) !== '$') { - if (key.indexOf('input') === 0) { - control[key.charAt(5).toLowerCase() + key.substr(6)] = value; - } else { - inputEl.attr(snake_case(key, '-'), value); - } + if (key.charAt(0) !== '$' && ['src','uiInput'].indexOf(key) === -1) { + inputEl.attr(snake_case(key, '-'), value); } }); //prepare validation messages - control.validation = angular.extend({}, uiConfig.uiinput.validation, scope.$eval(tAttrs.validation)); + input.validation = angular.extend({}, uiConfig.input.validation, scope.$eval(tAttrs.validation)); //expose model to a field's template - childScope.$control = control; - $compile(element.contents())(childScope); - childScope.$field = inputEl.controller('ngModel'); + scope.$input = input; + $compile(element.contents())(scope); + scope.$field = inputEl.controller('ngModel'); }); }; } }; -}]) - .directive('uiInput', ['InputHelper', function (InputHelper) { - return InputHelper; -}]) - .directive('uiTextarea', ['InputHelper', function (InputHelper) { - return InputHelper; -}]) - .directive('uiSelect', ['InputHelper', function (InputHelper) { - return InputHelper; }]); \ No newline at end of file From ae88061b680cee9f213629a00a4ef24344041642 Mon Sep 17 00:00:00 2001 From: Dean Sofer Date: Thu, 1 Nov 2012 01:31:48 -0700 Subject: [PATCH 3/3] Fixed the compiling bug thanks to @ajoslin --- modules/directives/input/input.js | 57 ++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/modules/directives/input/input.js b/modules/directives/input/input.js index 9561f74..82107eb 100644 --- a/modules/directives/input/input.js +++ b/modules/directives/input/input.js @@ -1,3 +1,23 @@ +/* +Test HTML + + +
+ +
+ +
Model: {{input|json}}
+ +
+
+ + */ angular.module('ui.directives') .directive('uiInput', ['$compile', '$http', '$templateCache', 'ui.config', function ($compile, $http, $templateCache, uiConfig) { @@ -51,30 +71,35 @@ angular.module('ui.directives') compile:function compile(tElement, tAttrs, transclude, uiForm) { var model = tAttrs.ngModel, input = { - id:tAttrs.id || 'input' + nextUid(idUid) + id:tAttrs.id || 'id' + nextUid(idUid) }; return function (scope, element, attrs) { - //infer a field type from template's tag name (can be one of ui-input, ui-select, ui-textarea) - $http.get(scope.$eval(attrs.src), {cache:$templateCache}).success(function (response) { + scope.$watch(attrs.src, function(newVal, oldVal) { + if (!newVal) + return; + $http.get(newVal, {cache:$templateCache}).success(function (response) { - element.html(response); + element.html(response); - var inputEl = element.find('[ng-transclude]'); - angular.forEach(tAttrs, function (value, key) { - if (key.charAt(0) !== '$' && ['src','uiInput'].indexOf(key) === -1) { - inputEl.attr(snake_case(key, '-'), value); - } - }); + var inputEl = element.find('[ng-transclude]'); + angular.forEach(tAttrs, function (value, key) { + if (key.charAt(0) !== '$' && ['src','uiInput', 'id'].indexOf(key) === -1) { + inputEl.attr(snake_case(key, '-'), value); + input[key] = value; + } + }); + inputEl.removeAttr('ng-transclude'); - //prepare validation messages - input.validation = angular.extend({}, uiConfig.input.validation, scope.$eval(tAttrs.validation)); + //prepare validation messages + input.validation = angular.extend({}, uiConfig.input.validation, scope.$eval(tAttrs.validation)); - //expose model to a field's template - scope.$input = input; - $compile(element.contents())(scope); - scope.$field = inputEl.controller('ngModel'); + //expose model to a field's template + scope.$input = input; + $compile(element.contents())(scope); + scope.$field = inputEl.controller('ngModel'); + }); }); }; }