From 489c26741b44f68d94070408b0b611af31b974b0 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Sun, 30 Nov 2014 15:52:49 -0800 Subject: [PATCH] CRM-15578 - Add directive --- js/angular-crm-ui.js | 79 ++++++++++++++++++++++++++++++++++++ partials/crmUi/field-cb.html | 8 ++++ partials/crmUi/field.html | 10 +++++ 3 files changed, 97 insertions(+) create mode 100644 partials/crmUi/field-cb.html create mode 100644 partials/crmUi/field.html diff --git a/js/angular-crm-ui.js b/js/angular-crm-ui.js index 70d2605c82..aa60943845 100644 --- a/js/angular-crm-ui.js +++ b/js/angular-crm-ui.js @@ -27,6 +27,85 @@ }; }) + // Display a field/row in a field list + // example:
{{mydata}}
+ // example:
+ // example:
+ .directive('crmUiField', function() { + function createReqStyle(req) { + return {visibility: req ? 'inherit' : 'hidden'}; + } + // Note: When writing new templates, the "label" position is particular. See/patch "var label" below. + var templateUrls = { + default: partialUrl('field.html'), + checkbox: partialUrl('field-cb.html') + }; + + return { + scope: { + crmUiField: '@', // string, name of an HTML form element + crmLayout: '@', // string, "default" or "checkbox" + crmTitle: '@' // expression, printable title for the field + }, + templateUrl: function(tElement, tAttrs){ + var layout = tAttrs.crmLayout ? tAttrs.crmLayout : 'default'; + return templateUrls[layout]; + }, + transclude: true, + link: function (scope, element, attrs) { + $(element).addClass('crm-section'); + scope.crmTitle = attrs.crmTitle; + scope.crmUiField = attrs.crmUiField; + scope.cssClasses = {}; + scope.crmRequiredStyle = createReqStyle(false); + + // 0. Ensure that a target field has been specified + + if (!attrs.crmUiField) return; + if (attrs.crmUiField == 'name') { + throw new Error('Validation monitoring does not work for field name "name"'); + } + + // 1. Figure out form and input elements + + var form = $(element).closest('form'); + var formCtrl = scope.$parent.$eval(form.attr('name')); + var input = $('input[name="' + attrs.crmUiField + '"],select[name="' + attrs.crmUiField + '"],textarea[name="' + attrs.crmUiField + '"]', form); + var label = $('>div.label >label, >label', element); + if (form.length != 1 || input.length != 1 || label.length != 1) { + if (console.log) console.log('Label cannot be matched to input element. Expected to find one form and one input[name='+attrs.crmUiField+'].', form.length, input.length, label.length); + return; + } + + // 2. Make sure that inputs are well-defined (with name+id). + + if (!input.attr('id')) { + input.attr('id', 'crmUi_' + (++idCount)); + } + $(label).attr('for', input.attr('id')); + + // 3. Monitor is the "required" and "$valid" properties + + if (input.attr('ng-required')) { + scope.crmRequiredStyle = createReqStyle(scope.$parent.$eval(input.attr('ng-required'))); + scope.$parent.$watch(input.attr('ng-required'), function(isRequired) { + scope.crmRequiredStyle = createReqStyle(isRequired); + }); + } else { + scope.crmRequiredStyle = createReqStyle(input.prop('required')); + } + + var inputCtrl = form.attr('name') + '.' + input.attr('name'); + scope.$parent.$watch(inputCtrl + '.$valid', function(newValue) { + scope.cssClasses['crm-error'] = !scope.$parent.$eval(inputCtrl + '.$valid') && !scope.$parent.$eval(inputCtrl + '.$pristine'); + }); + scope.$parent.$watch(inputCtrl + '.$pristine', function(newValue) { + scope.cssClasses['crm-error'] = !scope.$parent.$eval(inputCtrl + '.$valid') && !scope.$parent.$eval(inputCtrl + '.$pristine'); + }); + } + }; + }) + // example: .directive('crmUiIframe', function ($parse) { return { diff --git a/partials/crmUi/field-cb.html b/partials/crmUi/field-cb.html new file mode 100644 index 0000000000..944fcd2ecb --- /dev/null +++ b/partials/crmUi/field-cb.html @@ -0,0 +1,8 @@ + +
diff --git a/partials/crmUi/field.html b/partials/crmUi/field.html new file mode 100644 index 0000000000..bf77d86f1b --- /dev/null +++ b/partials/crmUi/field.html @@ -0,0 +1,10 @@ +
+ +
+
+
-- 2.25.1