blob: 83a206a43dccb40a5fc20929fa2cd9e9753067a2 [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 * ],
35 * fields: {
36 * field_name: {
37 * label: 'Field Label',
38 * type: 'string' // options are: [date, boolean, number, email, string],
39 * validators: {
40 * minlength: number,
41 maxlength: number,
42 required: boolean,
43 min: number,
44 max: number
45 * }
46 * }
47 * }
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070048 * }
49 * ```
50 * @element ANY
51 * @scope
Matteo Scandolo974c0e42016-05-25 16:02:16 -070052 * @requires xos.uiComponents.directive:xosField
53 * @requires xos.uiComponents.XosFormHelpers
54 * @requires xos.helpers._
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070055 * @example
Matteo Scandolo71378f92016-04-28 14:16:45 -070056
57 Autogenerated form
58
Matteo Scandolo840260d2016-04-22 09:56:48 -070059 <example module="sampleForm">
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070060 <file name="script.js">
Matteo Scandolo840260d2016-04-22 09:56:48 -070061 angular.module('sampleForm', ['xos.uiComponents'])
Matteo Scandolo199ec002016-04-22 10:53:49 -070062 .factory('_', function($window){
63 return $window._;
64 })
Matteo Scandolo840260d2016-04-22 09:56:48 -070065 .controller('SampleCtrl', function(){
66 this.model = {
Matteo Scandolo199ec002016-04-22 10:53:49 -070067 first_name: 'Jhon',
68 last_name: 'Doe',
69 email: 'jhon.doe@sample.com',
70 active: true,
71 birthDate: '2015-02-17T22:06:38.059000Z'
Matteo Scandolo840260d2016-04-22 09:56:48 -070072 }
73 this.config = {
74 exclude: ['password', 'last_login'],
75 formName: 'sampleForm',
76 actions: [
77 {
78 label: 'Save',
79 icon: 'ok', // refers to bootstraps glyphicon
80 cb: (user) => { // receive the model
81 console.log(user);
82 },
83 class: 'success'
84 }
85 ]
Matteo Scandolo7bc39c42016-04-20 11:38:42 -070086 };
87 });
88 </file>
Matteo Scandolo71378f92016-04-28 14:16:45 -070089 <file name="index.html">
90 <div ng-controller="SampleCtrl as vm">
91 <xos-form ng-model="vm.model" config="vm.config"></xos-form>
92 </div>
93 </file>
94 </example>
95
96 Configuration defined form
97
98 <example module="sampleForm1">
99 <file name="script.js">
100 angular.module('sampleForm1', ['xos.uiComponents'])
101 .factory('_', function($window){
102 return $window._;
103 })
104 .controller('SampleCtrl1', function(){
105 this.model = {
106 };
107
108 this.config = {
109 exclude: ['password', 'last_login'],
110 formName: 'sampleForm1',
111 actions: [
112 {
113 label: 'Save',
114 icon: 'ok', // refers to bootstraps glyphicon
115 cb: (user) => { // receive the model
116 console.log(user);
117 },
118 class: 'success'
119 }
120 ],
121 fields: {
122 first_name: {
123 type: 'string',
124 validators: {
125 required: true
126 }
127 },
128 last_name: {
129 label: 'Surname',
130 type: 'string',
131 validators: {
132 required: true,
133 minlength: 10
134 }
135 },
136 age: {
137 type: 'number',
138 validators: {
139 required: true,
140 min: 21
141 }
142 },
143 }
144 };
145 });
146 </file>
147 <file name="index.html">
148 <div ng-controller="SampleCtrl1 as vm">
149 <xos-form ng-model="vm.model" config="vm.config"></xos-form>
150 </div>
151 </file>
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700152 </example>
153
154 **/
155
156 .directive('xosForm', function(){
157 return {
158 restrict: 'E',
159 scope: {
160 config: '=',
161 ngModel: '='
162 },
163 template: `
arpiagariud4f6db12016-06-06 15:25:28 -0700164 <form name="vm.{{vm.config.formName || 'form'}}" novalidate>
Matteo Scandolo6e2e6ff2016-04-20 14:59:39 -0700165 <div class="form-group" ng-repeat="(name, field) in vm.formField">
arpiagariud4f6db12016-06-06 15:25:28 -0700166 <!--{{vm.ngModel[name] | json}}-->
Matteo Scandolo974c0e42016-05-25 16:02:16 -0700167 <xos-field name="name" field="field" ng-model="vm.ngModel[name]"></xos-field>
arpiagariud4f6db12016-06-06 15:25:28 -0700168 <!--<pre>{{vm[vm.config.formName] || 'form' | json }}</pre>-->
169 <!--{{field}}-->
170 <xos-validation field="vm[vm.config.formName || 'form'][name]" form = "vm[vm.config.formName || 'form']"></xos-validation>
171 <div class="alert alert-info" ng-show="(field.hint).length >0" role="alert">{{field.hint}}</div>
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700172 </div>
173 <div class="form-group" ng-if="vm.config.actions">
arpiagariu4a872ad2016-06-10 13:13:36 -0700174 <!--<pre>{{vm.config.feedback}} | json</pre>-->
175
176 <xos-alert config="vm.config.feedback" show="vm.config.feedback.show">{{vm.config.feedback.message}}</xos-alert>
177
Matteo Scandolo4ba4cf12016-04-20 16:36:17 -0700178 <button role="button" href=""
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700179 ng-repeat="action in vm.config.actions"
arpiagariu4a872ad2016-06-10 13:13:36 -0700180 ng-click="action.cb(vm.ngModel, vm[vm.config.formName || 'form'])"
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700181 class="btn btn-{{action.class}}"
182 title="{{action.label}}">
183 <i class="glyphicon glyphicon-{{action.icon}}"></i>
184 {{action.label}}
185 </button>
186 </div>
arpiagariud4f6db12016-06-06 15:25:28 -0700187 </form>
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700188 `,
189 bindToController: true,
190 controllerAs: 'vm',
Matteo Scandolo9f0e5ae2016-04-20 12:24:52 -0700191 controller: function($scope, $log, _, XosFormHelpers){
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700192
193 if(!this.config){
194 throw new Error('[xosForm] Please provide a configuration via the "config" attribute');
195 }
196
197 if(!this.config.actions){
198 throw new Error('[xosForm] Please provide an action list in the configuration');
199 }
200
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700201 this.excludedField = ['id', 'validators', 'created', 'updated', 'deleted', 'backend_status'];
202 if(this.config && this.config.exclude){
203 this.excludedField = this.excludedField.concat(this.config.exclude);
204 }
205
206
207 this.formField = [];
arpiagariu4a872ad2016-06-10 13:13:36 -0700208 $scope.$watch(() => this.config, ()=> {
Matteo Scandoloe2ee2d92016-04-27 15:58:16 -0700209
arpiagariu4a872ad2016-06-10 13:13:36 -0700210
211
212 if(!this.ngModel){
213 return;
214 }
215 let diff = _.difference(Object.keys(this.ngModel), this.excludedField);
216 let modelField = XosFormHelpers.parseModelField(diff);
217 this.formField = XosFormHelpers.buildFormStructure(modelField, this.config.fields, this.ngModel);
218
219
220 } ,true);
221
222
223 $scope.$watch(() => this.ngModel, (model) => {
Matteo Scandoloe2ee2d92016-04-27 15:58:16 -0700224 // empty from old stuff
225 this.formField = {};
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700226 if(!model){
227 return;
228 }
Matteo Scandoloe2ee2d92016-04-27 15:58:16 -0700229 let diff = _.difference(Object.keys(model), this.excludedField);
230 let modelField = XosFormHelpers.parseModelField(diff);
231 this.formField = XosFormHelpers.buildFormStructure(modelField, this.config.fields, model);
232 });
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700233
234 }
235 }
Matteo Scandolo974c0e42016-05-25 16:02:16 -0700236 });
Matteo Scandolo7bc39c42016-04-20 11:38:42 -0700237})();