blob: a246f9f00998d80b44603d8cbe1433a30dc8e8b5 [file] [log] [blame]
Matteo Scandoloa5d03d52016-07-21 11:35:46 -07001/**
2 * © OpenCORD
3 *
4 * Visit http://guide.xosproject.org/devguide/addview/ for more information
5 *
6 * Created by teone on 5/25/16.
7 */
8
9(function () {
10 'use strict';
11
12 angular.module('xos.uiComponents')
13 /**
14 * @ngdoc directive
15 * @name xos.uiComponents.directive:xosField
16 * @restrict E
17 * @description The xos-field directive.
18 * This component decide, give a field wich kind of input it need to print.
19 * @param {string} name The field name
20 * @param {object} field The field configuration:
21 * ```
22 * {
23 * label: 'Label',
24 * type: 'number', //typeof field
25 * validators: {} // see xosForm for more details
26 * }
27 * ```
28 * @param {mixed} ngModel The field value
29 *
30 * @example
31
32 # Basic Example
33
34 <example module="sampleField1">
35 <file name="script.js">
36 angular.module('sampleField1', ['xos.uiComponents'])
37 .factory('_', function($window){
38 return $window._;
39 })
40 .controller('SampleCtrl', function(){
41 this.name = 'input-name';
42 this.field = {label: 'My String Value:', type: 'string'};
43 this.model = 'my string';
44 });
45 </file>
46 <file name="index.html">
47 <div ng-controller="SampleCtrl as vm">
48 <xos-field ng-model="vm.model" name="vm.name" field="vm.field"></xos-field>
49 </div>
50 </file>
51 </example>
52
53 # Possible Values
54
55 <example module="sampleField2">
56 <file name="script.js">
57 angular.module('sampleField2', ['xos.uiComponents'])
58 .factory('_', function($window){
59 return $window._;
60 })
61 .controller('SampleCtrl', function(){
62 this.field1 = {
63 name: 'number-field',
64 field: {label: 'My Number Value:', type: 'number'},
65 model: 2
66 };
67
68 this.field2 = {
69 name: 'date-field',
70 field: {label: 'My Date Value:', type: 'date'},
71 model: new Date()
72 };
73
74 this.field3 = {
75 name: 'boolean-field',
76 field: {label: 'My Boolean Value:', type: 'boolean'},
77 model: true
78 };
79
80 this.field4 = {
81 name: 'email-field',
82 field: {label: 'My Email Value:', type: 'email'},
83 model: 'sample@domain.us'
84 };
85 });
86 </file>
87 <file name="index.html">
88 <div ng-controller="SampleCtrl as vm">
89 <xos-field ng-model="vm.field1.model" name="vm.field1.name" field="vm.field1.field"></xos-field>
90 <xos-field ng-model="vm.field2.model" name="vm.field2.name" field="vm.field2.field"></xos-field>
91 <xos-field ng-model="vm.field3.model" name="vm.field3.name" field="vm.field3.field"></xos-field>
92 <xos-field ng-model="vm.field4.model" name="vm.field4.name" field="vm.field4.field"></xos-field>
93 </div>
94 </file>
95 </example>
96
97 # This element is recursive
98
99 <example module="sampleField3">
100 <file name="script.js">
101 angular.module('sampleField3', ['xos.uiComponents'])
102 .factory('_', function($window){
103 return $window._;
104 })
105 .controller('SampleCtrl', function(){
106 this.name1 = 'input-name';
107 this.field1 = {label: 'My Object Field:', type: 'object'};
108 this.model1 = {
109 name: 'Jhon',
110 age: '25',
111 email: 'jhon@thewall.ru',
112 active: true
113 };
114
115 this.name2 = 'another-name';
116 this.field2 = {
117 label: 'Empty Object Field',
118 type: 'object',
119 properties: {
120 foo: {
121 label: 'FooLabel:',
122 type: 'string',
123 validators: {
124 required: true
125 }
126 },
127 bar: {
128 type: 'number'
129 }
130 }
131 }
132 });
133 </file>
134 <file name="index.html">
135 <div ng-controller="SampleCtrl as vm">
136 <h4>Autogenerated object field</h4>
137 <xos-field ng-model="vm.model1" name="vm.name1" field="vm.field1"></xos-field>
138
139 <h4>Configured object field</h4>
140 <xos-field ng-model="vm.model2" name="vm.name2" field="vm.field2"></xos-field>
141 </div>
142 </file>
143 </example>
144 */
Arpit Agarwal34b63832016-08-08 11:59:45 -0700145 .component('xosField', {
146 restrict: 'E',
147 bindings: {
148 name: '=',
149 field: '=',
150 ngModel: '='
151 },
152 template: `
153 <label ng-if="vm.field.type !== 'object'">{{vm.field.label}}</label>
154 <input
155 xos-custom-validator custom-validator="vm.field.validators.custom || null"
156 ng-if="vm.field.type !== 'boolean' && vm.field.type !== 'object' && vm.field.type !== 'select'"
157 type="{{vm.field.type}}"
158 name="{{vm.name}}"
159 class="form-control"
160 ng-model="vm.ngModel"
161 ng-minlength="vm.field.validators.minlength || 0"
162 ng-maxlength="vm.field.validators.maxlength || 2000"
163 ng-required="vm.field.validators.required || false" />
164 <select class="form-control" ng-if ="vm.field.type === 'select'"
165 name = "{{vm.name}}"
166 ng-options="item.id as item.label for item in vm.field.options"
Matteo Scandoloa5d03d52016-07-21 11:35:46 -0700167 ng-model="vm.ngModel"
Arpit Agarwal34b63832016-08-08 11:59:45 -0700168 ng-required="vm.field.validators.required || false">
169 </select>
170 <span class="boolean-field" ng-if="vm.field.type === 'boolean'">
171 <a href="#"
172 class="btn btn-success"
173 ng-show="vm.ngModel"
174 ng-click="vm.ngModel = false">
175 <i class="glyphicon glyphicon-ok"></i>
176 </a>
177 <a href="#"
178 class="btn btn-danger"
179 ng-show="!vm.ngModel"
180 ng-click="vm.ngModel = true">
181 <i class="glyphicon glyphicon-remove"></i>
182 </a>
183 </span>
184 <div
185 class="panel panel-default object-field"
186 ng-if="vm.field.type == 'object' && (!vm.isEmptyObject(vm.ngModel) || !vm.isEmptyObject(vm.field.properties))"
187 >
188 <div class="panel-heading">{{vm.field.label}}</div>
189 <div class="panel-body">
190 <div ng-if="!vm.field.properties" ng-repeat="(k, v) in vm.ngModel">
191 <xos-field
192 name="k"
193 field="{label: vm.formatLabel(k), type: vm.getType(v)}"
194 ng-model="v">
195 </xos-field>
196 </div>
197 <div ng-if="vm.field.properties" ng-repeat="(k, v) in vm.field.properties">
198 <xos-field
199 name="k"
200 field="{
201 label: v.label || vm.formatLabel(k),
202 type: v.type,
203 validators: v.validators
204 }"
205 ng-model="vm.ngModel[k]">
206 </xos-field>
Matteo Scandoloa5d03d52016-07-21 11:35:46 -0700207 </div>
208 </div>
Arpit Agarwal34b63832016-08-08 11:59:45 -0700209 </div>
210 `,
211 bindToController: true,
212 controllerAs: 'vm',
213 // the compile cicle is needed to support recursion
214 //compile: function (element) {
215 // return RecursionHelper.compile(element);
216 //},
217 controller: function($attrs, XosFormHelpers, LabelFormatter){
Matteo Scandoloa5d03d52016-07-21 11:35:46 -0700218
Arpit Agarwal34b63832016-08-08 11:59:45 -0700219 if(!this.name){
220 throw new Error('[xosField] Please provide a field name');
Matteo Scandoloa5d03d52016-07-21 11:35:46 -0700221 }
Arpit Agarwal34b63832016-08-08 11:59:45 -0700222 if(!this.field){
223 throw new Error('[xosField] Please provide a field definition');
224 }
225 if(!this.field.type){
226 throw new Error('[xosField] Please provide a type in the field definition');
227 }
228 if(!$attrs.ngModel){
229 throw new Error('[xosField] Please provide an ng-model');
230 }
231 this.getType = XosFormHelpers._getFieldFormat;
232 this.formatLabel = LabelFormatter.format;
233
234 this.isEmptyObject = o => o ? Object.keys(o).length === 0 : true;
Matteo Scandoloa5d03d52016-07-21 11:35:46 -0700235 }
236 })
237
238/**
239 * @ngdoc directive
240 * @name xos.uiComponents.directive:xosCustomValidator
241 * @restrict A
242 * @description The xosCustomValidator directive.
243 * This component apply a custom validation function
244 * @param {function} customValidator The function that execute the validation.
245 *
246 * You should do your validation here and return true | false,
247 * or alternatively you can return an array [errorName, true|false]
248 */
249 .directive('xosCustomValidator', function(){
250 return {
251 restrict: 'A',
252 scope: {
253 fn: '=customValidator'
254 },
255 require: 'ngModel',
256 link: function(scope, element, attr, ctrl){
257 if(!angular.isFunction(scope.fn)){
258 return;
259 }
260
261 function customValidatorWrapper(ngModelValue) {
262 const valid = scope.fn(ngModelValue);
263 if(angular.isArray(valid)){
264 // ES6 spread rocks over fn.apply()
265 ctrl.$setValidity(...valid);
266 }
267 else{
268 ctrl.$setValidity('custom', valid);
269 }
270 return ngModelValue;
271 }
272
273 ctrl.$parsers.push(customValidatorWrapper);
274 }
275 };
276 });
277})();