blob: 4d9169b5a2c9ea66e47e4cc2fd06ae4abe1d05b6 [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 4/18/16.
7 */
8
9(function () {
10 'use strict';
11
12
13 angular.module('xos.uiComponents')
14
15 /**
16 * @ngdoc directive
17 * @name xos.uiComponents.directive:xosForm
18 * @restrict E
19 * @description The xos-form directive.
20 * This components have two usage, given a model it is able to autogenerate a form or it can be configured to create a custom form.
21 * @param {Object} config The configuration object
22 * ```
23 * {
24 * exclude: ['id', 'validators', 'created', 'updated', 'deleted'], //field to be skipped in the form, the provide values are concatenated
25 * actions: [ // define the form buttons with related callback
26 * {
27 label: 'save',
28 icon: 'ok', // refers to bootstraps glyphicon
29 cb: (user) => { // receive the model
30 console.log(user);
31 },
32 class: 'success'
33 }
34 * ],
35 * feedback: {
36 show: false,
37 message: 'Form submitted successfully !!!',
38 type: 'success' //refers to bootstrap class
39 },
40 * fields: {
41 * field_name: {
42 * label: 'Field Label',
43 * type: 'string' // options are: [date, boolean, number, email, string, select],
44 * validators: {
45 * minlength: number,
46 maxlength: number,
47 required: boolean,
48 min: number,
49 max: number,
50 custom: (value) => {
51 // do your validation here and return true | false
52 // alternatively you can return an array [errorName, true|false]
53 }
54 * }
55 * }
56 * }
57 * }
58 * ```
59 * @element ANY
60 * @scope
61 * @requires xos.uiComponents.directive:xosField
62 * @requires xos.uiComponents.XosFormHelpers
63 * @requires xos.helpers._
64 * @example
65
66 Autogenerated form
67
68 <example module="sampleForm">
69 <file name="script.js">
70 angular.module('sampleForm', ['xos.uiComponents'])
71 .factory('_', function($window){
72 return $window._;
73 })
74 .controller('SampleCtrl', function(){
75 this.model = {
76 first_name: 'Jhon',
77 last_name: 'Doe',
78 email: 'jhon.doe@sample.com',
79 active: true,
80 birthDate: '2015-02-17T22:06:38.059000Z'
81 }
82 this.config = {
83 exclude: ['password', 'last_login'],
84 formName: 'sampleForm',
85 actions: [
86 {
87 label: 'Save',
88 icon: 'ok', // refers to bootstraps glyphicon
89 cb: (user) => { // receive the model
90 console.log(user);
91 },
92 class: 'success'
93 }
94 ]
95 };
96 });
97 </file>
98 <file name="index.html">
99 <div ng-controller="SampleCtrl as vm">
100 <xos-form ng-model="vm.model" config="vm.config"></xos-form>
101 </div>
102 </file>
103 </example>
104
105 Configuration defined form
106
107 <example module="sampleForm1">
108 <file name="script.js">
109 angular.module('sampleForm1', ['xos.uiComponents','ngResource', 'ngMockE2E'])
110 .factory('_', function($window){
111 return $window._;
112 })
113 .controller('SampleCtrl1', function(SampleResource){
114
115
116 this.model = {
117 };
118
119 this.config = {
120 exclude: ['password', 'last_login'],
121 formName: 'sampleForm1',
122 feedback: {
123 show: false,
124 message: 'Form submitted successfully !!!',
125 type: 'success'
126 },
127 actions: [
128 {
129 label: 'Save',
130 icon: 'ok', // refers to bootstraps glyphicon
131 cb: (user) => { // receive the model
132 console.log(user);
133 this.config.feedback.show = true;
134 this.config.feedback.type='success';
135 },
136 class: 'success'
137 }
138 ],
139 fields: {
140 first_name: {
141 type: 'string',
142 validators: {
143 required: true
144 }
145 },
146 last_name: {
147 label: 'Surname',
148 type: 'string',
149 validators: {
150 required: true,
151 minlength: 10
152 }
153 },
154 age: {
155 type: 'number',
156 validators: {
157 required: true,
158 min: 21
159 }
160 },
161
162 site: {
163 label: 'Site',
164 type: 'select',
165 validators: { required: true},
166 hint: 'The Site this Slice belongs to',
167 options: []
168 },
169 }
170 };
171 SampleResource.query().$promise
172 .then((users) => {
173 //this.users_site = users;
174 //console.log(users);
175 this.optionVal = users;
176 this.config.fields['site'].options = this.optionVal;
177 //= this.optionVal;
178
179 })
180 .catch((e) => {
181 throw new Error(e);
182 });
183
184 });
185 </file>
186 <file name="backend.js">
187 angular.module('sampleForm1')
188 .run(function($httpBackend, _){
189 let datas = [{id: 1, label: 'site1'},{id: 4, label: 'site4'},{id: 3, label: 'site3'}];
190 let paramsUrl = new RegExp(/\/test\/(.+)/);
191 $httpBackend.whenGET('/test').respond(200, datas)
192 })
193 .service('SampleResource', function($resource){
194 return $resource('/test/:id', {id: '@id'});
195 });
196
197 </file>
198 <file name="index.html">
199 <div ng-controller="SampleCtrl1 as vm">
200 <xos-form ng-model="vm.model" config="vm.config"></xos-form>
201 </div>
202 </file>
203 </example>
204
205 **/
206
207 .directive('xosForm', function(){
208 return {
209 restrict: 'E',
210 scope: {
211 config: '=',
212 ngModel: '='
213 },
214 template: `
215 <form name="vm.{{vm.config.formName || 'form'}}" novalidate>
216 <div class="form-group" ng-repeat="(name, field) in vm.formField">
217 <xos-field name="name" field="field" ng-model="vm.ngModel[name]"></xos-field>
218 <xos-validation field="vm[vm.config.formName || 'form'][name]" form = "vm[vm.config.formName || 'form']"></xos-validation>
219 <div class="alert alert-info" ng-show="(field.hint).length >0" role="alert">{{field.hint}}</div>
220 </div>
221 <div class="form-group" ng-if="vm.config.actions">
222 <xos-alert config="vm.config.feedback" show="vm.config.feedback.show">{{vm.config.feedback.message}}</xos-alert>
223
224 <button role="button" href=""
225 ng-repeat="action in vm.config.actions"
226 ng-click="action.cb(vm.ngModel, vm[vm.config.formName || 'form'])"
227 class="btn btn-{{action.class}}"
228 title="{{action.label}}">
229 <i class="glyphicon glyphicon-{{action.icon}}"></i>
230 {{action.label}}
231 </button>
232 </div>
233 </form>
234 `,
235 bindToController: true,
236 controllerAs: 'vm',
237 controller: function($scope, $log, _, XosFormHelpers){
238
239 if(!this.config){
240 throw new Error('[xosForm] Please provide a configuration via the "config" attribute');
241 }
242
243 if(!this.config.actions){
244 throw new Error('[xosForm] Please provide an action list in the configuration');
245 }
246
247 if(!this.config.feedback){
248 this.config.feedback = {
249 show: false,
250 message: 'Form submitted successfully !!!',
251 type: 'success'
252 }
253 }
254
255 this.excludedField = ['id', 'validators', 'created', 'updated', 'deleted', 'backend_status'];
256 if(this.config && this.config.exclude){
257 this.excludedField = this.excludedField.concat(this.config.exclude);
258 }
259
260 this.formField = [];
261
262 $scope.$watch(() => this.config, ()=> {
263 if(!this.ngModel){
264 return;
265 }
266 let diff = _.difference(Object.keys(this.ngModel), this.excludedField);
267 let modelField = XosFormHelpers.parseModelField(diff);
268 this.formField = XosFormHelpers.buildFormStructure(modelField, this.config.fields, this.ngModel);
269 }, true);
270
271 $scope.$watch(() => this.ngModel, (model) => {
272 // empty from old stuff
273 this.formField = {};
274 if(!model){
275 return;
276 }
277 let diff = _.difference(Object.keys(model), this.excludedField);
278 let modelField = XosFormHelpers.parseModelField(diff);
279 this.formField = XosFormHelpers.buildFormStructure(modelField, this.config.fields, model);
280 });
281
282 }
283 }
284 });
285})();