@processmaker/screen-builder 2.22.0 → 2.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package-lock.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@processmaker/screen-builder",
3
- "version": "2.22.0",
3
+ "version": "2.24.1",
4
4
  "lockfileVersion": 1,
5
5
  "requires": true,
6
6
  "dependencies": {
@@ -1738,9 +1738,9 @@
1738
1738
  }
1739
1739
  },
1740
1740
  "@processmaker/vue-form-elements": {
1741
- "version": "0.28.5",
1742
- "resolved": "https://registry.npmjs.org/@processmaker/vue-form-elements/-/vue-form-elements-0.28.5.tgz",
1743
- "integrity": "sha512-vnThQAH0TI/ZSMl4GPQA8H+AooPyv65RZnQzaBEWKUeFSpdwFFUJUIc1lMH4ji4L3qKPBEy/qQFhB541QFeh2w==",
1741
+ "version": "0.28.6",
1742
+ "resolved": "https://registry.npmjs.org/@processmaker/vue-form-elements/-/vue-form-elements-0.28.6.tgz",
1743
+ "integrity": "sha512-uxHsOkCNLJEF4mJu7dK4+qn2SL/mWDswdoV1kQjNjQkwBk10uGXDdAbtliHRbld3HDMAPUQAu69c+1fS8pDqjA==",
1744
1744
  "dev": true,
1745
1745
  "requires": {
1746
1746
  "@tinymce/tinymce-vue": "2.0.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@processmaker/screen-builder",
3
- "version": "2.22.0",
3
+ "version": "2.24.1",
4
4
  "scripts": {
5
5
  "serve": "vue-cli-service serve",
6
6
  "build": "vue-cli-service build",
@@ -44,7 +44,7 @@
44
44
  "@cypress/code-coverage": "^3.8.1",
45
45
  "@fortawesome/fontawesome-free": "^5.6.1",
46
46
  "@panter/vue-i18next": "^0.15.2",
47
- "@processmaker/vue-form-elements": "0.28.5",
47
+ "@processmaker/vue-form-elements": "0.28.6",
48
48
  "@processmaker/vue-multiselect": "^2.2.0",
49
49
  "@vue/cli-plugin-babel": "^3.6.0",
50
50
  "@vue/cli-plugin-e2e-cypress": "^4.0.3",
@@ -85,7 +85,7 @@
85
85
  },
86
86
  "peerDependencies": {
87
87
  "@panter/vue-i18next": "^0.15.0",
88
- "@processmaker/vue-form-elements": "0.28.5",
88
+ "@processmaker/vue-form-elements": "0.28.6",
89
89
  "i18next": "^15.0.8",
90
90
  "vue": "^2.6.12",
91
91
  "vuex": "^3.1.1"
package/src/.DS_Store CHANGED
Binary file
@@ -1,6 +1,6 @@
1
1
  import { validators } from './mixins/ValidationRules';
2
2
  import DataProvider from './DataProvider';
3
- import { get, set } from 'lodash';
3
+ import { get, set, merge } from 'lodash';
4
4
  import { Parser } from 'expr-eval';
5
5
 
6
6
  let globalObject = typeof window === 'undefined'
@@ -34,7 +34,7 @@ class Validations {
34
34
  isVisible() {
35
35
  // Disable validations if field is hidden
36
36
  let visible = true;
37
- if (this.element.config.conditionalHide) {
37
+ if (!this.data.noData && this.element.config.conditionalHide) {
38
38
  try {
39
39
  visible = !!Parser.evaluate(this.element.config.conditionalHide, this.data);
40
40
  } catch (error) {
@@ -51,7 +51,7 @@ class Validations {
51
51
  class ArrayOfFieldsValidations extends Validations {
52
52
  async addValidations(validations) {
53
53
  for (const item of this.element) {
54
- await ValidationsFactory(item, { screen: this.screen, data: this.data }).addValidations(validations);
54
+ await ValidationsFactory(item, { screen: this.screen, data: this.data, parentVisibilityRule: this.parentVisibilityRule }).addValidations(validations);
55
55
  }
56
56
  }
57
57
  }
@@ -81,8 +81,9 @@ class FormNestedScreenValidations extends Validations {
81
81
  return;
82
82
  }
83
83
  const definition = await this.loadScreen(this.element.config.screen);
84
+ let parentVisibilityRule = this.parentVisibilityRule ? this.parentVisibilityRule : this.element.config.conditionalHide;
84
85
  if (definition && definition[0] && definition[0].items) {
85
- await ValidationsFactory(definition[0].items, { screen: this.screen, data: this.data }).addValidations(validations);
86
+ await ValidationsFactory(definition[0].items, { screen: this.screen, data: this.data, parentVisibilityRule }).addValidations(validations);
86
87
  }
87
88
  }
88
89
 
@@ -112,8 +113,53 @@ class FormLoopValidations extends Validations {
112
113
  set(validations, this.element.config.name, {});
113
114
  const loopField = get(validations, this.element.config.name);
114
115
  loopField['$each'] = {};
115
- const firstRow = (get(this.data, this.element.config.name) || [{}])[0];
116
- await ValidationsFactory(this.element.items, { screen: this.screen, data: {_parent: this.data, ...firstRow } }).addValidations(loopField['$each']);
116
+ this.checkForSiblings(validations);
117
+ await ValidationsFactory(this.element.items, { screen: this.screen, data: {_parent: this.data, noData:true }, parentVisibilityRule: this.element.config.conditionalHide }).addValidations(loopField['$each']);
118
+ }
119
+ checkForSiblings(validations) {
120
+ const siblings = [];
121
+ const siblingValidations = [];
122
+ // Find loops that reference the same variable
123
+ this.screen.config.forEach(page => {
124
+ page.items.filter(item => {
125
+ if (item.component === 'FormLoop' && item.config.name === this.element.config.name) {
126
+ siblings.push(item);
127
+ }
128
+ });
129
+
130
+ // Get siblings validations
131
+ if (siblings) {
132
+ siblings.forEach(sibling => {
133
+ sibling.items.filter(item => {
134
+ if (!item.config.validation) {
135
+ return;
136
+ }
137
+
138
+ item.config.validation.forEach(validation => {
139
+ const rule = this.camelCase(validation.value.split(':')[0]);
140
+ const validationFn = validators[rule];
141
+ const obj = {};
142
+ let ruleObj = {};
143
+ ruleObj[rule] = validationFn;
144
+ obj[item.config.name] = ruleObj;
145
+ merge(siblingValidations, obj);
146
+ });
147
+ });
148
+ });
149
+ }
150
+ });
151
+
152
+ if (Object.keys(siblingValidations).length != 0) {
153
+ // Update the loop validations with its siblings.
154
+ const loopValidations = get(validations, this.element.config.name);
155
+ if (loopValidations.hasOwnProperty('$each')) {
156
+ merge(loopValidations['$each'], siblingValidations);
157
+ }
158
+ set(validations[this.element.config.name]['$each'], loopValidations);
159
+ }
160
+ }
161
+ camelCase(name) {
162
+ return name.replace(/_\w/g, m => m.substr(1, 1).toUpperCase());
117
163
  }
118
164
  }
119
165
 
@@ -126,7 +172,7 @@ class FormMultiColumnValidations extends Validations {
126
172
  if (!this.isVisible()) {
127
173
  return;
128
174
  }
129
- await ValidationsFactory(this.element.items, { screen: this.screen, data: this.data }).addValidations(validations);
175
+ await ValidationsFactory(this.element.items, { screen: this.screen, data: this.data, parentVisibilityRule: this.element.config.conditionalHide }).addValidations(validations);
130
176
  }
131
177
  }
132
178
 
@@ -168,7 +214,7 @@ class FormElementValidations extends Validations {
168
214
  const fieldName = this.element.config.name;
169
215
  const validationConfig = this.element.config.validation;
170
216
  const conditionalHide = this.element.config.conditionalHide;
171
-
217
+ const parentVisibilityRule = this.parentVisibilityRule;
172
218
 
173
219
  set(validations, fieldName, get(validations, fieldName, {}));
174
220
  const fieldValidation = get(validations, fieldName);
@@ -194,7 +240,25 @@ class FormElementValidations extends Validations {
194
240
  }
195
241
  fieldValidation[rule] = function(...props) {
196
242
  const data = props[1];
197
- const dataWithParent = this.addReferenceToParents(data);
243
+ let dataWithParent = this.addReferenceToParents(data);
244
+ const nestedDataWithParent = this.addReferenceToParents(this.findParent(data));
245
+ if (nestedDataWithParent) {
246
+ dataWithParent = Object.assign(nestedDataWithParent, dataWithParent);
247
+ }
248
+ // Check Parent Visibility
249
+ if (parentVisibilityRule) {
250
+ let isParentVisible = true;
251
+ try {
252
+ isParentVisible = !!Parser.evaluate(parentVisibilityRule, dataWithParent);
253
+ } catch (error) {
254
+ isParentVisible = false;
255
+ }
256
+
257
+ if (!isParentVisible ) {
258
+ return true;
259
+ }
260
+ }
261
+ // Check Field Visibility
198
262
  let visible = true;
199
263
  if (conditionalHide) {
200
264
  try {
@@ -218,7 +282,25 @@ class FormElementValidations extends Validations {
218
282
  }
219
283
  fieldValidation[validationConfig] = function(...props) {
220
284
  const data = props[1];
221
- const dataWithParent = this.addReferenceToParents(data);
285
+ let dataWithParent = this.addReferenceToParents(data);
286
+ const nestedDataWithParent = this.addReferenceToParents(this.findParent(data));
287
+ if (nestedDataWithParent) {
288
+ dataWithParent = Object.assign(nestedDataWithParent, dataWithParent);
289
+ }
290
+ // Check Parent Visibility
291
+ if (parentVisibilityRule) {
292
+ let isParentVisible = true;
293
+ try {
294
+ isParentVisible = !!Parser.evaluate(parentVisibilityRule, dataWithParent);
295
+ } catch (error) {
296
+ isParentVisible = false;
297
+ }
298
+
299
+ if (!isParentVisible) {
300
+ return true;
301
+ }
302
+ }
303
+ // Check Field Visibility
222
304
  let visible = true;
223
305
  if (conditionalHide) {
224
306
  try {
@@ -20,10 +20,13 @@
20
20
  :data-manager="dataManager"
21
21
  :fields="tableFields"
22
22
  :items="tableData.data"
23
+ :sort-compare-options="{ numeric: false }"
23
24
  sort-icon-left
24
25
  :css="css"
25
26
  :empty-text="$t('No Data Available')"
26
27
  :current-page="currentPage"
28
+ @sort-changed="sortChanged"
29
+ @input="onInput"
27
30
  data-cy="table"
28
31
  >
29
32
  <template #cell()="{index,field,item}">
@@ -163,7 +166,7 @@ const jsonOptionsActionsColumn = {
163
166
 
164
167
  export default {
165
168
  mixins: [mustacheEvaluation],
166
- props: ['name', 'label', 'fields', 'value', 'editable', '_config', 'form', 'validationData', 'formConfig', 'formComputed', 'formWatchers'],
169
+ props: ['name', 'label', 'fields', 'value', 'editable', '_config', 'form', 'validationData', 'formConfig', 'formComputed', 'formWatchers', '_perPage'],
167
170
  data() {
168
171
  return {
169
172
  editFormVersion: 0,
@@ -194,6 +197,11 @@ export default {
194
197
  initFormValues: {},
195
198
  };
196
199
  },
200
+ mounted() {
201
+ if (this._perPage) {
202
+ this.perPage = this._perPage;
203
+ }
204
+ },
197
205
  computed: {
198
206
  popupConfig() {
199
207
  const config = [];
@@ -242,6 +250,7 @@ export default {
242
250
  from,
243
251
  to: value.length,
244
252
  data: value,
253
+ lastSortConfig: false,
245
254
  };
246
255
  return data;
247
256
  },
@@ -260,7 +269,32 @@ export default {
260
269
  return this.form && this.form === this.$parent.currentPage;
261
270
  },
262
271
  },
272
+ watch: {
273
+ 'tableData.total': {
274
+ deep: true,
275
+ handler(total) {
276
+ let totalPages = Math.ceil(total / this.perPage);
277
+ this.currentPage = (this.currentPage > totalPages ? totalPages : this.currentPage);
278
+ this.currentPage = (this.currentPage == 0 ? 1 : this.currentPage);
279
+ },
280
+ },
281
+ },
263
282
  methods: {
283
+ sortChanged(payload) {
284
+ this.lastSortConfig = payload;
285
+ this.tableData.data = this.sort(this.tableData.data, payload);
286
+ },
287
+ onInput() {
288
+ if (this.lastSortConfig) {
289
+ this.tableData.data = this.sort(this.tableData.data, this.lastSortConfig);
290
+ }
291
+ },
292
+ sort(data, options) {
293
+ if (options.sortDesc) {
294
+ return data.sort((b,a) => a[options.sortBy].localeCompare(b[options.sortBy], 0, {numeric: false}));
295
+ }
296
+ return data.sort((a,b) => a[options.sortBy].localeCompare(b[options.sortBy], 0, {numeric: false}));
297
+ },
264
298
  emitShownEvent() {
265
299
  window.ProcessMaker.EventBus.$emit('modal-shown');
266
300
  },
@@ -342,9 +376,9 @@ export default {
342
376
  }
343
377
  },
344
378
  showEditForm(index) {
345
- let pageIndex = ((this.paginatorPage-1) * this.perPage) + index;
379
+ let pageIndex = ((this.currentPage-1) * this.perPage) + index;
346
380
  // Reset edit to be a copy of our data model item
347
- this.editItem = JSON.parse(JSON.stringify(this.value[pageIndex]));
381
+ this.editItem = JSON.parse(JSON.stringify(this.tableData.data[pageIndex]));
348
382
  this.editIndex = pageIndex;
349
383
  // rebuild the edit screen to avoid
350
384
  this.editFormVersion++;
@@ -354,13 +388,13 @@ export default {
354
388
  });
355
389
  },
356
390
  edit(event) {
357
- if (this.$refs.editRenderer.$refs.renderer.$refs.component.$v.$invalid) {
391
+ if (this.$refs.editRenderer.$refs.renderer.$refs.component.$v.vdata.$invalid) {
358
392
  event.preventDefault();
359
393
  return;
360
394
  }
361
395
 
362
396
  // Edit the item in our model and emit change
363
- let data = this.value ? JSON.parse(JSON.stringify(this.value)) : [];
397
+ let data = this.tableData.data ? JSON.parse(JSON.stringify(this.tableData.data)) : [];
364
398
  data[this.editIndex] = JSON.parse(JSON.stringify(this.editItem));
365
399
 
366
400
  // Remove the parent object
@@ -387,7 +421,7 @@ export default {
387
421
  handleOk(bvModalEvt) {
388
422
  bvModalEvt.preventDefault();
389
423
 
390
- if (this.$refs.addRenderer.$refs.renderer.$refs.component.$v.$invalid) {
424
+ if (this.$refs.addRenderer.$refs.renderer.$refs.component.$v.vdata.$invalid) {
391
425
  return;
392
426
  }
393
427
 
@@ -410,7 +444,7 @@ export default {
410
444
  });
411
445
  },
412
446
  showDeleteConfirmation(index) {
413
- let pageIndex = ((this.paginatorPage-1) * this.perPage) + index;
447
+ let pageIndex = ((this.currentPage-1) * this.perPage) + index;
414
448
  this.deleteIndex = pageIndex;
415
449
  this.$refs.deleteModal.show();
416
450
  },
@@ -447,7 +481,7 @@ export default {
447
481
  remove() {
448
482
  // Add the item to our model and emit change
449
483
  // @todo Also check that value is an array type, if not, reset it to an array
450
- let data = this.value ? JSON.parse(JSON.stringify(this.value)) : [];
484
+ let data = this.tableData.data ? JSON.parse(JSON.stringify(this.tableData.data)) : [];
451
485
  let recordData = data[this.deleteIndex];
452
486
  // Remove item from data array
453
487
  data.splice(this.deleteIndex, 1);
@@ -464,3 +498,4 @@ export default {
464
498
  max-width: 300px;
465
499
  }
466
500
  </style>
501
+
@@ -242,6 +242,11 @@ export default {
242
242
  .then((response) => {
243
243
  this.task = response.data;
244
244
  this.checkTaskStatus();
245
+ if (window.PM4ConfigOverrides.getScreenEndpoint && window.PM4ConfigOverrides.getScreenEndpoint.includes('tasks/')) {
246
+ const screenPath = window.PM4ConfigOverrides.getScreenEndpoint.split('/');
247
+ screenPath[1] = this.task.id;
248
+ window.PM4ConfigOverrides.getScreenEndpoint = screenPath.join('/');
249
+ }
245
250
  })
246
251
  .catch(() => {
247
252
  this.hasErrors = true;
@@ -279,19 +284,19 @@ export default {
279
284
  }
280
285
  this.prepareTask();
281
286
  },
282
- closeTask() {
287
+ closeTask(parentRequestId = null) {
283
288
  if (this.hasErrors) {
284
289
  this.$emit('error', this.requestId);
285
290
  return;
286
291
  }
287
292
 
288
293
  if (this.task.process_request.status === 'COMPLETED') {
289
- this.processCompleted();
294
+ this.loadNextAssignedTask(parentRequestId);
290
295
 
291
296
  } else if (this.task.allow_interstitial) {
292
297
  this.task.interstitial_screen['_interstitial'] = true;
293
298
  this.screen = this.task.interstitial_screen;
294
- this.loadNextAssignedTask();
299
+ this.loadNextAssignedTask(parentRequestId);
295
300
 
296
301
  } else {
297
302
  this.$emit('closed', this.task.id);
@@ -313,11 +318,16 @@ export default {
313
318
  }
314
319
  this.unsubscribeSocketListeners();
315
320
  this.redirecting = task.process_request_id;
316
- this.$emit('redirect', task);
321
+ this.$emit('redirect', task.id, true);
317
322
  return;
323
+ } else if (this.task && requestId == this.task.process_request_id && this.parentRequest && this.task.process_request.status === 'COMPLETED') {
324
+ // Only emit completed after getting the subprocess tasks and there are no tasks and process is completed
325
+ this.$emit('completed', this.parentRequest);
318
326
  }
319
327
  this.taskId = task.id;
320
328
  this.nodeId = task.element_id;
329
+ } else {
330
+ this.$emit('completed', (this.parentRequest ? this.parentRequest : requestId));
321
331
  }
322
332
  });
323
333
  },
@@ -361,9 +371,8 @@ export default {
361
371
  // This may no longer be needed
362
372
  },
363
373
  processCompleted() {
364
- if (this.parentRequest && this.task.allow_interstitial) {
365
- // There could be another task in the parent, so don't emit completed
366
- return;
374
+ if (this.parentRequest) {
375
+ this.$emit('completed', this.parentRequest);
367
376
  }
368
377
  this.$emit('completed', this.requestId);
369
378
  },
@@ -412,8 +421,13 @@ export default {
412
421
  `ProcessMaker.Models.ProcessRequest.${this.parentRequest}`,
413
422
  '.ProcessUpdated',
414
423
  (data) => {
415
- if (['ACTIVITY_COMPLETED', 'ACTIVITY_ACTIVATED'].includes(data.event)) {
416
- this.loadNextAssignedTask(this.parentRequest);
424
+ if (['ACTIVITY_ACTIVATED'].includes(data.event)) {
425
+ this.closeTask(this.parentRequest);
426
+ }
427
+ if (['ACTIVITY_COMPLETED'].includes(data.event)) {
428
+ if (this.task.process_request.status === 'COMPLETED') {
429
+ this.processCompleted();
430
+ }
417
431
  }
418
432
  if (data.event === 'ACTIVITY_EXCEPTION') {
419
433
  this.$emit('error', this.requestId);
package/src/main.js CHANGED
@@ -152,7 +152,7 @@ window.ProcessMaker = {
152
152
  {value: 2, content: 'John'},
153
153
  {value: 3, content: 'Mary'},
154
154
  {value: 4, content: 'Patricia'},
155
- ],
155
+ ],
156
156
  }});
157
157
  break;
158
158
  default:
@@ -201,6 +201,16 @@ window.Echo = {
201
201
  }, 1000);
202
202
  });
203
203
  },
204
+ eventMocks(event, response) {
205
+ this.listeners.forEach((listener) => {
206
+ setTimeout(() => {
207
+ listener.callback({
208
+ type: event,
209
+ response,
210
+ });
211
+ }, 1000);
212
+ });
213
+ },
204
214
  private() {
205
215
  return {
206
216
  notification(callback) {
@@ -93,7 +93,8 @@ export default {
93
93
  },
94
94
  tryFormField(variableName, callback, defaultValue = null) {
95
95
  try {
96
- return callback();
96
+ let result = callback();
97
+ return (result === undefined) ? null : result;
97
98
  } catch (e) {
98
99
  set(this.$v, `${variableName}.$invalid`, true);
99
100
  set(this.$v, `${variableName}.invalid_default_value`, false);
@@ -154,21 +155,17 @@ export default {
154
155
  },
155
156
  setValue(name, value, object = this, defaults = object) {
156
157
  if (object && value !== undefined) {
157
- const splittedName = name.split('.');
158
- splittedName.forEach((attr, index) => {
158
+ const parsedName = name.split('.');
159
159
 
160
- let isLastElement, setValue;
161
- const originalValue = get(object, attr);
160
+ for (const attr of parsedName) {
161
+ let setValue;
162
+ let index = parsedName.indexOf(attr);
163
+ let isLastElement = index === parsedName.length - 1;
162
164
 
163
- if (index === splittedName.length - 1) {
164
- isLastElement = true;
165
- } else {
166
- isLastElement = false;
167
- }
165
+ const originalValue = get(object, attr);
168
166
 
169
167
  if (isLastElement) {
170
168
  setValue = value;
171
-
172
169
  } else {
173
170
  setValue = originalValue;
174
171
 
@@ -176,7 +173,7 @@ export default {
176
173
  // Check defaults
177
174
  setValue = get(defaults, attr);
178
175
  }
179
-
176
+
180
177
  if (!setValue) {
181
178
  // Still no value? Set empty object
182
179
  setValue = {};
@@ -192,9 +189,10 @@ export default {
192
189
  attr,
193
190
  setValue
194
191
  );
192
+
195
193
  object = get(object, attr);
196
194
  defaults = get(defaults, attr);
197
- });
195
+ }
198
196
  }
199
197
  },
200
198
  validationMessage(validation) {
@@ -1,20 +1,24 @@
1
- import _ from 'lodash';
1
+ import { isEqual } from 'lodash';
2
2
  import { Parser } from 'expr-eval';
3
3
 
4
4
  export default {
5
5
  methods: {
6
6
  evaluateExpression(expression, type) {
7
+ const self = this;
7
8
  let value = null;
8
9
 
9
- const merged = {};
10
- _.merge(merged, this.vdata, this._data);
11
-
12
10
  try {
13
- //monitor if variable belongs to data (defined variables) or vdata (external variables)
14
- //in this way the event is not executed again when the variable is update
15
- const data = new Proxy(merged, {
11
+ // Monitor if variable belongs to data (defined variables) or
12
+ // vdata (external variables)in this way the event is not
13
+ // executed again when the variable is update
14
+
15
+ const data = new Proxy(Object.assign({}, this), {
16
16
  get(data, name) {
17
- return data[name];
17
+ if (data[name] === undefined || !isEqual(data[name]), self.vdata[name]) {
18
+ return self.vdata[name];
19
+ } else {
20
+ return data[name];
21
+ }
18
22
  },
19
23
  set() {
20
24
  throw 'You are not allowed to set properties from inside an expression';
@@ -3,14 +3,28 @@ import computedFields from '../computedFields';
3
3
  export default {
4
4
  methods: {
5
5
  computedFields(screen, definition) {
6
+ // Add computed fields
6
7
  screen.mixins.push(computedFields);
7
- definition.computed.forEach(computed => {
8
+
9
+ for (const computed of definition.computed) {
8
10
  screen.computed[computed.property] = {
9
- get: new Function(`return this.evaluateExpression(${JSON.stringify(computed.formula)}, ${JSON.stringify(computed.type)});`),
10
- set() {},
11
+ get: (() => {
12
+ const formula = JSON.stringify(computed.formula);
13
+ const type = JSON.stringify(computed.type);
14
+
15
+ return new Function(`return this.evaluateExpression(${formula}, ${type});`);
16
+ })(),
17
+ set() {
18
+ // Do nothing (as it's not allowed)
19
+ },
11
20
  };
12
- this.addWatch(screen, computed.property, `this.setValue(${JSON.stringify(computed.property)}, value, this.vdata);`);
13
- });
21
+
22
+ this.addWatch(
23
+ screen,
24
+ computed.property,
25
+ `this.setValue(${JSON.stringify(computed.property)}, value, this.vdata);`
26
+ );
27
+ }
14
28
  },
15
29
  },
16
30
  mounted() {