blob: 89ef19234f7b33100f18f4b9d56be13d64005224 [file] [log] [blame]
Matteo Scandolo7bc39c42016-04-20 11:38:42 -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
Matteo Scandolo5dfcb082016-05-31 15:15:00 -070012
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070013 angular.module('xos.uiComponents')
14
15 /**
16 * @ngdoc directive
17 * @name xos.uiComponents.directive:xosForm
18 * @restrict E
Matteo Scandolo71378f92016-04-28 14:16:45 -070019 * @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.
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070021 * @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 }
Matteo Scandolo71378f92016-04-28 14:16:45 -070034 * ],
arpiagariu98680a52016-06-14 14:08:45 -070035 * feedback: {
36 show: false,
37 message: 'Form submitted successfully !!!',
38 type: 'success' //refers to bootstrap class
39 },
Matteo Scandolo71378f92016-04-28 14:16:45 -070040 * fields: {
41 * field_name: {
42 * label: 'Field Label',
arpiagariu98680a52016-06-14 14:08:45 -070043 * type: 'string' // options are: [date, boolean, number, email, string, select],
Matteo Scandolo71378f92016-04-28 14:16:45 -070044 * validators: {
arpiagariu98680a52016-06-14 14:08:45 -070045 * minlength: number,
Matteo Scandolo71378f92016-04-28 14:16:45 -070046 maxlength: number,
47 required: boolean,
48 min: number,
Matteo Scandolod6585762016-06-15 18:03:43 -070049 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 }
Matteo Scandolo71378f92016-04-28 14:16:45 -070054 * }
55 * }
56 * }
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070057 * }
58 * ```
59 * @element ANY
60 * @scope
Matteo Scandolo974c0e42016-05-25 16:02:16 -070061 * @requires xos.uiComponents.directive:xosField
62 * @requires xos.uiComponents.XosFormHelpers
63 * @requires xos.helpers._
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070064 * @example
Matteo Scandolo71378f92016-04-28 14:16:45 -070065
66 Autogenerated form
67
Matteo Scandolo840260d2016-04-22 09:56:48 -070068 <example module="sampleForm">
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070069 <file name="script.js">
Matteo Scandolo840260d2016-04-22 09:56:48 -070070 angular.module('sampleForm', ['xos.uiComponents'])
Matteo Scandolo199ec002016-04-22 10:53:49 -070071 .factory('_', function($window){
72 return $window._;
73 })
Matteo Scandolo840260d2016-04-22 09:56:48 -070074 .controller('SampleCtrl', function(){
75 this.model = {
Matteo Scandolo199ec002016-04-22 10:53:49 -070076 first_name: 'Jhon',
77 last_name: 'Doe',
78 email: 'jhon.doe@sample.com',
79 active: true,
80 birthDate: '2015-02-17T22:06:38.059000Z'
Matteo Scandolo840260d2016-04-22 09:56:48 -070081 }
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 ]
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070095 };
96 });
97 </file>
Matteo Scandolo71378f92016-04-28 14:16:45 -070098 <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">
arpiagariu98680a52016-06-14 14:08:45 -0700109 angular.module('sampleForm1', ['xos.uiComponents','ngResource', 'ngMockE2E'])
Matteo Scandolo71378f92016-04-28 14:16:45 -0700110 .factory('_', function($window){
111 return $window._;
112 })
arpiagariu98680a52016-06-14 14:08:45 -0700113 .controller('SampleCtrl1', function(SampleResource){
114
115
Matteo Scandolo71378f92016-04-28 14:16:45 -0700116 this.model = {
117 };
118
119 this.config = {
120 exclude: ['password', 'last_login'],
121 formName: 'sampleForm1',
arpiagariu98680a52016-06-14 14:08:45 -0700122 feedback: {
123 show: false,
124 message: 'Form submitted successfully !!!',
125 type: 'success'
126 },
Matteo Scandolo71378f92016-04-28 14:16:45 -0700127 actions: [
128 {
129 label: 'Save',
130 icon: 'ok', // refers to bootstraps glyphicon
131 cb: (user) => { // receive the model
132 console.log(user);
arpiagariu98680a52016-06-14 14:08:45 -0700133 this.config.feedback.show = true;
134 this.config.feedback.type='success';
Matteo Scandolo71378f92016-04-28 14:16:45 -0700135 },
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 },
arpiagariu98680a52016-06-14 14:08:45 -0700161
162 site: {
163 label: 'Site',
164 type: 'select',
165 validators: { required: true},
166 hint: 'The Site this Slice belongs to',
167 options: []
168 },
169 }
Matteo Scandolo71378f92016-04-28 14:16:45 -0700170 };
arpiagariu98680a52016-06-14 14:08:45 -0700171 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);
Matteo Scandolo71378f92016-04-28 14:16:45 -0700182 });
arpiagariu98680a52016-06-14 14:08:45 -0700183
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
Matteo Scandolo71378f92016-04-28 14:16:45 -0700197 </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>
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700203 </example>
204
205 **/
206
207 .directive('xosForm', function(){
208 return {
209 restrict: 'E',
210 scope: {
211 config: '=',
212 ngModel: '='
213 },
214 template: `
arpiagariud4f6db12016-06-06 15:25:28 -0700215 <form name="vm.{{vm.config.formName || 'form'}}" novalidate>
Matteo Scandolo6e2e6ff2016-04-20 14:59:39 -0700216 <div class="form-group" ng-repeat="(name, field) in vm.formField">
Matteo Scandolo974c0e42016-05-25 16:02:16 -0700217 <xos-field name="name" field="field" ng-model="vm.ngModel[name]"></xos-field>
arpiagariud4f6db12016-06-06 15:25:28 -0700218 <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>
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700220 </div>
221 <div class="form-group" ng-if="vm.config.actions">
arpiagariu4a872ad2016-06-10 13:13:36 -0700222 <xos-alert config="vm.config.feedback" show="vm.config.feedback.show">{{vm.config.feedback.message}}</xos-alert>
223
Matteo Scandolo4ba4cf12016-04-20 16:36:17 -0700224 <button role="button" href=""
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700225 ng-repeat="action in vm.config.actions"
arpiagariu4a872ad2016-06-10 13:13:36 -0700226 ng-click="action.cb(vm.ngModel, vm[vm.config.formName || 'form'])"
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700227 class="btn btn-{{action.class}}"
228 title="{{action.label}}">
229 <i class="glyphicon glyphicon-{{action.icon}}"></i>
230 {{action.label}}
231 </button>
232 </div>
arpiagariud4f6db12016-06-06 15:25:28 -0700233 </form>
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700234 `,
235 bindToController: true,
236 controllerAs: 'vm',
Matteo Scandolo9f0e5ae2016-04-20 12:24:52 -0700237 controller: function($scope, $log, _, XosFormHelpers){
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700238
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
arpiagariu10bd9cb2016-06-10 13:28:34 -0700247 if(!this.config.feedback){
248 this.config.feedback = {
249 show: false,
250 message: 'Form submitted successfully !!!',
251 type: 'success'
252 }
253 }
254
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700255 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
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700260 this.formField = [];
Matteo Scandolob585d382016-06-15 14:53:33 -0700261
arpiagariu4a872ad2016-06-10 13:13:36 -0700262 $scope.$watch(() => this.config, ()=> {
arpiagariu4a872ad2016-06-10 13:13:36 -0700263 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);
Matteo Scandolob585d382016-06-15 14:53:33 -0700269 }, true);
arpiagariu4a872ad2016-06-10 13:13:36 -0700270
271 $scope.$watch(() => this.ngModel, (model) => {
Matteo Scandoloe2ee2d92016-04-27 15:58:16 -0700272 // empty from old stuff
273 this.formField = {};
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700274 if(!model){
275 return;
276 }
Matteo Scandoloe2ee2d92016-04-27 15:58:16 -0700277 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 });
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700281
282 }
283 }
Matteo Scandolo974c0e42016-05-25 16:02:16 -0700284 });
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700285})();