saasufy-components 3.2.0 → 3.4.0

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/README.md CHANGED
@@ -404,9 +404,9 @@ Used for displaying and editing a single field of a model instance in real time.
404
404
  - `debounce-delay`: The delay in milliseconds to wait before sending an update to the server. This is useful to batch multiple updates together (as is common when user is typing). Default is 300ms.
405
405
  - `input-id`: Can be used to set an `id` attribute on the inner `input` element.
406
406
  - `list`: If specified, this sets the list attribute of the inner `input` element to provide input suggestions (only works with standard input elements).
407
- - `type`: The type of the input component; can be `text`, `number`, `select`, `textarea` or `checkbox`.
407
+ - `type`: The type of the input component; can be `text`, `number`, `select`, `textarea`, `checkbox` or `file`.
408
408
  - `placeholder`: Can be used to set the placeholder text on the inner input element.
409
- - `consumers`: This allows you to connect this `model-input` to other elements on your page which share the same parent element. It takes a list of selectors with optional attributes to target. For example `.my-input:value` will find all elements with a `my-input` class and update their `value` attributes with the value of the `model-input` component in real-time. You can specify multiple selectors separated by commas such as `.my-input,my-div` - In this case, because attribute names are not specified, values will be injected into the `value` attribute (for input elements) or into the `innerHTML` property (for other kinds of elements). The default attribute/property depends on the element type.
409
+ - `consumers`: This allows you to connect this `model-input` to other elements on your page. It takes a list of selectors with optional attributes to target. For example `.my-input:value` will find all elements with a `my-input` class and update their `value` attributes with the value of the `model-input` component in real-time. You can specify multiple selectors separated by commas such as `.my-input,my-div` - In this case, because attribute names are not specified, values will be injected into the `value` attribute (for input elements) or into the `innerHTML` property (for other kinds of elements). The default attribute/property depends on the element type.
410
410
  - `provider-template`: A template string within which the `{{value}}` can be injected before passing to consumers.
411
411
  - `show-error-message`: If this attribute is present, an error message will be displayed above the input if it fails to update the value.
412
412
  - `options`: A comma-separated list of options to provide - This only works if the input type is `select`.
@@ -417,6 +417,7 @@ Used for displaying and editing a single field of a model instance in real time.
417
417
  - `autocapitalize`: Can be `on` or `off` - It will set the auto-capitalize attribute on the inner input element. This is useful for mobile devices to enable or disable auto-capitalization of the first character which is typed into the input element.
418
418
  - `autocorrect`: Can be `on` or `off` - It will set the auto-correct attribute on the inner input element. This is useful for mobile devices to enable or disable auto-correct.
419
419
  - `enable-rebound`: By default, for efficiency reasons, real-time updates performed via `model-input` components are not sent back to the publishing client; it is usually unnecessary because state changes are shared locally between all components which are bound to the same `socket-provider`. You can add the `enable-rebound` attribute to the `model-input` component to force real-time updates to rebound back to the publisher to support more advanced scenarios. Note that enabling rebound comes with additional performance overheads.
420
+ - `accept`: This attribute should only be used if the `type` is set to `file`; it serves to constrain the types of files which can be selected by the user.
420
421
 
421
422
  ### model-text
422
423
 
@@ -513,7 +514,7 @@ This component can be configured to provide its data to multiple components (con
513
514
  - `list`: If specified, this sets the list attribute of the inner `input` element to provide input suggestions (only works with standard input elements).
514
515
  - `type`: The type of the input component; can be `text`, `number`, `select`, `textarea` or `checkbox`.
515
516
  - `placeholder`: Can be used to set the placeholder text on the inner input element.
516
- - `consumers`: This allows you to connect this `input-provider` to other elements on your page which share the same parent element. It takes a list of selectors with optional attributes to target. For example `.my-input:value` will find all elements with a `my-input` class and update their `value` attributes with the value of the `input-provider` component in real-time. You can specify multiple selectors separated by commas such as `.my-input,my-div` - In this case, because attribute names are not specified, values will be injected into the `value` attribute (for input elements) or into the `innerHTML` property (for other kinds of elements). The default attribute/property depends on the element type.
517
+ - `consumers`: This allows you to connect this `input-provider` to other elements on your page. It takes a list of selectors with optional attributes to target. For example `.my-input:value` will find all elements with a `my-input` class and update their `value` attributes with the value of the `input-provider` component in real-time. You can specify multiple selectors separated by commas such as `.my-input,my-div` - In this case, because attribute names are not specified, values will be injected into the `value` attribute (for input elements) or into the `innerHTML` property (for other kinds of elements). The default attribute/property depends on the element type.
517
518
  - `provider-template`: A template string within which the `{{value}}` can be injected before passing to consumers.
518
519
  - `debounce-delay`: The delay in milliseconds to wait before triggering a change event. This is useful to batch multiple updates together (as is common when user is typing). Default is 800ms.
519
520
  - `options`: A comma-separated list of options to provide - This only works if the input type is `select`.
@@ -738,7 +739,7 @@ A component which can be used to group together multiple `collection-adder` comp
738
739
 
739
740
  ```html
740
741
  <!--
741
- This collection-adder-group adds two pre-defined records into a Product
742
+ This collection-adder-group adds multiple pre-defined records into a Product
742
743
  collection using a single button click. This example assumes that the name
743
744
  field is the only required field in the Product model.
744
745
  -->
package/model-input.js CHANGED
@@ -26,6 +26,7 @@ class ModelInput extends SocketConsumer {
26
26
  'socket-instance-property',
27
27
  'type',
28
28
  'placeholder',
29
+ 'accept',
29
30
  'consumers',
30
31
  'show-error-message',
31
32
  'model-type',
@@ -95,6 +96,7 @@ class ModelInput extends SocketConsumer {
95
96
  let inputList = this.getAttribute('list');
96
97
  let type = this.getAttribute('type') || 'text';
97
98
  let placeholder = this.getAttribute('placeholder');
99
+ let accept = this.getAttribute('accept');
98
100
  let modelType = this.getAttribute('model-type');
99
101
  let modelId = this.getAttribute('model-id');
100
102
  let modelField = this.getAttribute('model-field');
@@ -102,6 +104,7 @@ class ModelInput extends SocketConsumer {
102
104
  let height = this.getAttribute('height');
103
105
  let hideErrorLogs = this.hasAttribute('hide-error-logs');
104
106
  let enableRebound = this.hasAttribute('enable-rebound');
107
+ let hasConsumers = this.hasAttribute('consumers');
105
108
 
106
109
  let socket;
107
110
  if (socketInstanceProperty) {
@@ -124,11 +127,14 @@ class ModelInput extends SocketConsumer {
124
127
  socket = this.getSocket();
125
128
  }
126
129
  this.socket = socket;
130
+
131
+ let modelFieldList = hasConsumers ? [ modelField ] : [];
132
+
127
133
  let model = new AGModel({
128
134
  socket: this.socket,
129
135
  type: modelType,
130
136
  id: modelId,
131
- fields: [ modelField ],
137
+ fields: modelFieldList,
132
138
  enableRebound
133
139
  });
134
140
  if (!hideErrorLogs) {
@@ -191,6 +197,9 @@ class ModelInput extends SocketConsumer {
191
197
  if (placeholder) {
192
198
  this.inputElement.setAttribute('placeholder', placeholder);
193
199
  }
200
+ if (accept) {
201
+ this.inputElement.setAttribute('accept', accept);
202
+ }
194
203
  let errorMessageContainer = null;
195
204
  if (showErrorMessage) {
196
205
  errorMessageContainer = document.createElement('div');
@@ -215,8 +224,11 @@ class ModelInput extends SocketConsumer {
215
224
  updateConsumerElements(consumers, checked, providerTemplate);
216
225
  } else {
217
226
  let defaultValue = this.getAttribute('default-value') || '';
218
- inputElement.value = fieldValue == null ? defaultValue : fieldValue;
219
- updateConsumerElements(consumers, inputElement.value, providerTemplate);
227
+ let elementValue = fieldValue == null ? defaultValue : fieldValue;
228
+ if (inputElement.type !== 'file') {
229
+ inputElement.value = elementValue;
230
+ }
231
+ updateConsumerElements(consumers, elementValue, providerTemplate);
220
232
  }
221
233
  }
222
234
 
@@ -278,12 +290,28 @@ class ModelInput extends SocketConsumer {
278
290
  hideErrorMessage(fieldName);
279
291
  return;
280
292
  }
281
- if (event.target.value === '') {
293
+ let inputValue;
294
+ if (inputElement.type === 'file' && inputElement.files && inputElement.files.length) {
295
+ let reader = new FileReader();
296
+ let readerLoadPromise = new Promise((resolve, reject) => {
297
+ reader.addEventListener('load', () => {
298
+ resolve(reader.result);
299
+ });
300
+ reader.addEventListener('error', () => {
301
+ reject(new Error('Failed to read file'));
302
+ });
303
+ });
304
+ reader.readAsDataURL(inputElement.files[0]);
305
+ inputValue = await readerLoadPromise;
306
+ } else {
307
+ inputValue = event.target.value;
308
+ }
309
+ if (inputValue === '') {
282
310
  updateConsumerElements(consumers, '', providerTemplate);
283
311
  await model.delete(fieldName);
284
312
  } else {
285
313
  let targetValue = inputElement.type === 'number' ?
286
- Number(event.target.value) : event.target.value;
314
+ Number(inputValue) : inputValue;
287
315
  updateConsumerElements(consumers, targetValue, providerTemplate);
288
316
  await model.update(fieldName, targetValue);
289
317
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "saasufy-components",
3
- "version": "3.2.0",
3
+ "version": "3.4.0",
4
4
  "description": "Components for Saasufy.",
5
5
  "main": "index.js",
6
6
  "scripts": {