@heroku/ember-hk-components 0.21.2 → 1.21.3

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.
@@ -0,0 +1,287 @@
1
+ # Migration Guide
2
+
3
+ This guide helps you migrate from the previous version of `ember-hk-components` to the latest version. Please read through all sections carefully as there are several important changes that may affect your application.
4
+
5
+ ## Overview
6
+
7
+ This update includes significant improvements to validation handling, dependency upgrades, and package management changes. The most notable changes are:
8
+
9
+ - Enhanced validation state management in `hk-field-validations`
10
+ - Major dependency upgrades (`ember-changeset-validations` v2 → v4)
11
+ - Migration from Yarn to pnpm
12
+ - Improved accessibility and modern Ember template syntax
13
+
14
+ ## Breaking Changes
15
+
16
+ ### 1. Dependency Updates
17
+
18
+ #### ember-changeset-validations (v2.2.1 → v4.0.0)
19
+
20
+ **Impact**: Major version upgrade with potential breaking changes.
21
+
22
+ **Action Required**:
23
+ 1. Review the [ember-changeset-validations v4 changelog](https://github.com/poteto/ember-changeset-validations/releases)
24
+ 2. Update your validation schemas if needed
25
+ 3. Test all form validation thoroughly
26
+
27
+ #### ember-a11y-testing (v4.4.0 → v5.2.1)
28
+
29
+ **Impact**: Major version upgrade affecting accessibility testing.
30
+
31
+ **Action Required**:
32
+ 1. Review the [ember-a11y-testing v5 migration guide](https://github.com/ember-a11y/ember-a11y-testing/releases)
33
+ 2. Update your test files if using this addon directly
34
+
35
+ ### 2. Package Manager Migration (Yarn → pnpm)
36
+
37
+ **Impact**: The project now enforces pnpm usage and removes yarn.lock.
38
+
39
+ **Action Required**:
40
+ ```bash
41
+ # Remove yarn.lock if present
42
+ rm yarn.lock
43
+
44
+ # Install pnpm if not already installed
45
+ npm install -g pnpm
46
+
47
+ # Install dependencies
48
+ pnpm install
49
+ ```
50
+
51
+ **Note**: The addon now includes a preinstall hook that enforces pnpm usage.
52
+
53
+ ### 3. Node.js Engine Requirements
54
+
55
+ **Impact**: Removed explicit Node.js engine constraints (previously required `14.x || 16.x`).
56
+
57
+ **Action Required**: Ensure you're using a supported Node.js version for your Ember CLI version.
58
+
59
+ ## Component Behavior Changes
60
+
61
+ ### hk-field-validations Component
62
+
63
+ The validation logic has been significantly refactored to provide more reliable validation state management.
64
+
65
+ #### Key Changes
66
+
67
+ 1. **Validation State Tracking**
68
+ - New internal `_hasValidatedFlag` for precise validation tracking
69
+ - `hasValidated` now considers both manual validation and changeset pristine state
70
+ - Improved handling of async validation promises
71
+
72
+ 2. **Enhanced Validation Timing**
73
+ - Better debounced validation with improved error handling
74
+ - More robust cleanup of observers and validation state
75
+ - Improved handling of component destruction during validation
76
+
77
+ 3. **Changeset Integration**
78
+ - `hasValidated` now returns `true` when changeset is no longer pristine
79
+ - This means validation errors may appear earlier than before
80
+ - Better integration with changeset lifecycle events
81
+
82
+ #### Migration Steps
83
+
84
+ 1. **Test Validation Behavior**
85
+ ```javascript
86
+ // Before: Validation only triggered after explicit user interaction
87
+ // After: Validation may trigger when changeset becomes non-pristine
88
+
89
+ // Test these scenarios:
90
+ // - Initial form load
91
+ // - First field interaction
92
+ // - Async validation timing
93
+ // - Form reset behavior
94
+ ```
95
+
96
+ 2. **Review Validation Timing**
97
+ If your application relies on specific validation timing, you may need to adjust:
98
+ ```javascript
99
+ // If you need the old behavior, you can check the internal flag:
100
+ // component.get('_hasValidatedFlag') // true only after explicit validation
101
+
102
+ // New behavior considers changeset state:
103
+ // component.get('hasValidated') // true when validated OR changeset not pristine
104
+ ```
105
+
106
+ ### hk-validation-errors-list Component
107
+
108
+ #### New Features
109
+
110
+ - Added `errorsListId` computed property for better accessibility
111
+ - Generates IDs like `validation-errors-${property}`
112
+
113
+ #### Migration Steps
114
+
115
+ **No action required** - this is a backward-compatible addition.
116
+
117
+ ## Template Syntax Updates
118
+
119
+ All component templates now use modern Ember syntax with `this.` prefix.
120
+
121
+ **Before**:
122
+ ```handlebars
123
+ {{yield (hash
124
+ value=value
125
+ isValidating=isValidating
126
+ isValid=isValid
127
+ isInvalid=isInvalid
128
+ errors=validationErrors
129
+ )}}
130
+ ```
131
+
132
+ **After**:
133
+ ```handlebars
134
+ {{yield (hash
135
+ value=this.value
136
+ isValidating=this.isValidating
137
+ isValid=this.isValid
138
+ isInvalid=this.isInvalid
139
+ errors=this.validationErrors
140
+ )}}
141
+ ```
142
+
143
+ **Impact**: No breaking changes for consumers, but improves consistency with modern Ember practices.
144
+
145
+ ## Development Environment Changes
146
+
147
+ ### ESLint Configuration
148
+
149
+ - Updated to use `@babel/eslint-parser`
150
+ - Removed `babel-eslint` dependency
151
+
152
+ ### Removed Dependencies
153
+
154
+ - `ember-cli-chai` - removed from devDependencies
155
+ - `npm-run-all` - replaced with direct pnpm commands
156
+
157
+ ### Security Updates
158
+
159
+ Added package resolutions for security vulnerabilities:
160
+ ```json
161
+ {
162
+ "resolutions": {
163
+ "lodash.template": "npm:lodash@^4.17.21",
164
+ "braces": "npm:braces@^3.0.3",
165
+ "rollup": "^4.50.1",
166
+ "json5": "^2.2.3",
167
+ "ansi-html": "^0.0.8",
168
+ "consolidate": "npm:@ladjs/consolidate@^1.0.0",
169
+ "validated-changeset": "1.4.1"
170
+ }
171
+ }
172
+ ```
173
+
174
+ ## Testing Recommendations
175
+
176
+ ### 1. Validation Testing
177
+
178
+ Create comprehensive tests for validation behavior:
179
+
180
+ ```javascript
181
+ import { module, test } from 'qunit';
182
+ import { setupRenderingTest } from 'ember-qunit';
183
+ import { render, fillIn, blur } from '@ember/test-helpers';
184
+ import { hbs } from 'ember-cli-htmlbars';
185
+
186
+ module('Integration | Component | your-form', function(hooks) {
187
+ setupRenderingTest(hooks);
188
+
189
+ test('validation timing works correctly', async function(assert) {
190
+ // Test initial state
191
+ await render(hbs`{{your-form-component}}`);
192
+
193
+ // Test validation on changeset modification
194
+ await fillIn('input', 'invalid-value');
195
+ // Assert validation state
196
+
197
+ // Test validation on blur
198
+ await blur('input');
199
+ // Assert validation state
200
+
201
+ // Test async validation
202
+ await fillIn('input', 'async-validation-trigger');
203
+ // Wait for validation to complete
204
+ // Assert final state
205
+ });
206
+ });
207
+ ```
208
+
209
+ ### 2. Accessibility Testing
210
+
211
+ If using `ember-a11y-testing`, update your tests:
212
+
213
+ ```javascript
214
+ // Update import if needed
215
+ import a11yAudit from 'ember-a11y-testing/test-support/audit';
216
+
217
+ test('accessibility compliance', async function(assert) {
218
+ await render(hbs`{{your-component}}`);
219
+ await a11yAudit(this.element);
220
+ assert.ok(true, 'no a11y errors found');
221
+ });
222
+ ```
223
+
224
+ ### 3. Integration Testing
225
+
226
+ Test the complete validation flow:
227
+
228
+ ```javascript
229
+ test('complete validation flow', async function(assert) {
230
+ // Test initial pristine state
231
+ // Test first interaction
232
+ // Test validation errors display
233
+ // Test error clearing
234
+ // Test form submission with errors
235
+ // Test successful validation
236
+ });
237
+ ```
238
+
239
+ ## Troubleshooting
240
+
241
+ ### Common Issues
242
+
243
+ 1. **Validation errors appear too early**
244
+ - This is likely due to the new `hasValidated` logic
245
+ - Review your form initialization and changeset setup
246
+ - Consider if the new behavior is actually more user-friendly
247
+
248
+ 2. **Async validation issues**
249
+ - The component now has better handling of async validation
250
+ - Check that your validation functions return promises correctly
251
+ - Ensure proper error handling in your validators
252
+
253
+ 3. **Package installation issues**
254
+ - Make sure you're using pnpm, not npm or yarn
255
+ - Clear node_modules and reinstall if needed: `rm -rf node_modules && pnpm install`
256
+
257
+ 4. **ESLint errors**
258
+ - Update your ESLint configuration if you have custom rules
259
+ - The addon now uses `@babel/eslint-parser`
260
+
261
+ ### Getting Help
262
+
263
+ If you encounter issues during migration:
264
+
265
+ 1. Check the component documentation
266
+ 2. Review the test files for usage examples
267
+ 3. Open an issue with a minimal reproduction case
268
+
269
+ ## Rollback Plan
270
+
271
+ If you need to rollback:
272
+
273
+ 1. Revert to the previous version in package.json
274
+ 2. Run `pnpm install` (or your package manager)
275
+ 3. Restore any custom validation logic you may have modified
276
+
277
+ ## Summary
278
+
279
+ This update significantly improves the reliability and user experience of form validation while maintaining backward compatibility for most use cases. The main areas requiring attention are:
280
+
281
+ - Validation timing behavior (may show errors sooner)
282
+ - Package manager migration to pnpm
283
+ - Testing of async validation scenarios
284
+ - Dependency compatibility (especially ember-changeset-validations v4)
285
+
286
+ Take time to thoroughly test your forms after upgrading, particularly focusing on validation timing and error display behavior.
287
+
package/Procfile ADDED
@@ -0,0 +1 @@
1
+ web: bin/start-nginx-static
package/README.md CHANGED
@@ -1,20 +1,35 @@
1
1
  # Ember HK Components
2
2
 
3
- Reusable Ember components
3
+ Reusable Ember components for Heroku applications.
4
4
 
5
5
  ## Assumptions
6
6
 
7
7
  Usage of these components assumes you are using the [Purple3 CSS framework](https://purple3.herokuapp.com/) and [Malibu](https://hk-malibu.herokuapp.com).
8
8
 
9
+ ## Security
10
+
11
+ This project maintains high security standards and regularly addresses vulnerabilities through:
12
+
13
+ - **Automated vulnerability scanning** via `pnpm audit`
14
+ - **Strategic dependency resolutions** to address transitive vulnerabilities
15
+ - **Regular dependency updates** while maintaining compatibility
16
+ - **Comprehensive security documentation** (see `BABEL_TRAVERSE_VULNERABILITY_GUIDE.md`)
17
+
18
+ For security-related questions or to report vulnerabilities, please follow Heroku's security guidelines.
19
+
9
20
  ## Usage
10
21
 
11
22
  ### Installation
12
23
 
13
- 1. Install `ember-cli-eyeglass` if it's not installed already.
14
- `ember install --save ember-cli-eyeglass`
24
+ 1. Install `ember-cli-eyeglass` if it's not installed already:
25
+ ```bash
26
+ ember install ember-cli-eyeglass
27
+ ```
15
28
 
16
- 2. Install `@heroku/ember-hk-components`
17
- `ember install --save @heroku/ember-hk-components`
29
+ 2. Install `@heroku/ember-hk-components`:
30
+ ```bash
31
+ ember install @heroku/ember-hk-components
32
+ ```
18
33
 
19
34
  #### CSS
20
35
 
@@ -39,7 +54,7 @@ See [ember-hk-components.herokuapp.com](https://ember-hk-components.herokuapp.co
39
54
 
40
55
  * `git clone https://github.com/heroku/ember-hk-components`
41
56
  * `cd ember-hk-components`
42
- * `yarn install`
57
+ * `pnpm install`
43
58
 
44
59
  ### Running
45
60
 
@@ -48,27 +63,69 @@ See [ember-hk-components.herokuapp.com](https://ember-hk-components.herokuapp.co
48
63
 
49
64
  ### Running Tests
50
65
 
51
- * `yarn test` (Runs `ember try:each` to test your addon against multiple Ember versions)
66
+ * `pnpm test` (Runs `ember try:each` to test your addon against multiple Ember versions)
52
67
  * `ember test`
53
68
  * `ember test --server`
54
69
 
70
+ ### Security Auditing
71
+
72
+ This project uses PNPM for enhanced security and performance:
73
+
74
+ * `pnpm audit` - Check for security vulnerabilities
75
+ * `pnpm audit --fix` - Automatically fix resolvable vulnerabilities
76
+
77
+ See `BABEL_TRAVERSE_VULNERABILITY_GUIDE.md` for detailed security resolution strategies.
78
+
55
79
  ### Local Usage in Another Application
56
80
 
57
- The demo app is useful for developing this addon, but it can often be helpful to consume your version of this addon in another application either to more easily develop your changes or to validate that your changes work as you expect. You can use your local version of `ember-hk-components` in another application that consumes it via yarn's [link](https://yarnpkg.com/lang/en/docs/cli/link/) command.
81
+ The demo app is useful for developing this addon, but it can often be helpful to consume your version of this addon in another application either to more easily develop your changes or to validate that your changes work as you expect. You can use your local version of `ember-hk-components` in another application that consumes it via PNPM's [link](https://pnpm.io/cli/link) command.
58
82
 
59
83
  ```sh
60
84
  // in your ember-hk-components directory
61
- > yarn link
85
+ > pnpm link --global
62
86
 
63
87
  // in your consuming app directory
64
- > yarn link @heroku/ember-hk-components
88
+ > pnpm link --global @heroku/ember-hk-components
65
89
 
66
90
  // to put consuming app back on the release version
67
- > yarn unlink @heroku/ember-hk-components
91
+ > pnpm unlink --global @heroku/ember-hk-components
92
+ > pnpm install @heroku/ember-hk-components
68
93
  ```
69
94
 
70
95
  Now, when you make changes in your copy of `ember-hk-components` those changes will be reflected in the consuming application.
71
96
 
97
+ ### Package Management
98
+
99
+ This project has migrated from Yarn to PNPM for:
100
+
101
+ - **Enhanced security** through stricter dependency resolution
102
+ - **Better performance** with content-addressable storage
103
+ - **Improved workspace support** for monorepo scenarios
104
+ - **Advanced resolution strategies** for vulnerability mitigation
105
+
106
+ All package management commands should use `pnpm` instead of `npm` or `yarn`.
107
+
108
+ ### Recent Security Improvements
109
+
110
+ This project has recently undergone significant security hardening:
111
+
112
+ #### Vulnerability Resolution
113
+ - **Critical babel-traverse vulnerability** resolved via strategic package resolutions
114
+ - **High-severity vulnerabilities** in `rollup`, `json5`, `ansi-html` addressed
115
+ - **Transitive dependency vulnerabilities** mitigated through `@ladjs/consolidate` adoption
116
+
117
+ #### Dependency Updates
118
+ - **ember-a11y-testing** updated to `^5.2.1` for better compatibility
119
+ - **Package resolutions** strategically implemented for security without breaking changes
120
+ - **Comprehensive audit process** documented for future maintenance
121
+
122
+ #### Security Documentation
123
+ - `BABEL_TRAVERSE_VULNERABILITY_GUIDE.md` - Comprehensive guide for resolving babel-traverse vulnerabilities
124
+ - Detailed troubleshooting and implementation strategies
125
+ - Best practices for maintaining security in Ember CLI projects
126
+
127
+ For more details on security implementations, see the vulnerability guide and recent changelog entries.
128
+
72
129
  ### Releases
73
130
 
74
131
  #### Notes
@@ -88,12 +145,12 @@ Once you are ready to make a new release follow these steps:
88
145
  * Ensure all merged pull requests are labelled correctly as indicated in the Changelog section
89
146
  * Create a new branch
90
147
  * Update the version number in `package.json`
91
- * Run `yarn run changelog --from x.x.x` where `x.x.x` is the _last_ version of this library that was released. This should generate changelog of changes _since_ that last release.
92
- * Copy the output of that command into Changelog.md
148
+ * Run `pnpm run changelog --from x.x.x` where `x.x.x` is the _last_ version of this library that was released. This should generate changelog of changes _since_ that last release.
149
+ * Copy the output of that command into `CHANGELOG.md`
93
150
  * Commit your changes and open a PR
94
151
 
95
152
  Once the PR is approved and merged you can then tag your new version by running `git tag x.x.x` where `x.x.x` is the new version number. Push your tag to GitHub using `git push origin --tags`.
96
153
 
97
- Publish your new version to npm with the command `npm publish` 🎉
154
+ Publish your new version to npm with the command `pnpm publish` 🎉
98
155
 
99
156
  _Note that you must have publish access to the @heroku npm organization to successfully publish_
@@ -1,6 +1,6 @@
1
1
  import Component from '@ember/component';
2
2
  import { computed, get } from '@ember/object';
3
- import { alias, and, notEmpty, not } from '@ember/object/computed';
3
+ import { alias, and, not, notEmpty, or } from '@ember/object/computed';
4
4
  import { debounce } from '@ember/runloop';
5
5
  import layout from '@heroku/ember-hk-components/templates/components/hk-field-validations';
6
6
 
@@ -8,92 +8,120 @@ export default Component.extend({
8
8
  layout,
9
9
  classNameBindings: ['isInvalid:has-validation-errors'],
10
10
  debounceValidation: 1000,
11
+
12
+ // Use a manual flag for validation state
11
13
  isValidating: false,
12
14
  isNotValidating: not('isValidating'),
13
- hasValidated: false,
15
+
16
+ _hasValidatedFlag: false,
17
+
18
+ // A field has been validated if it was triggered internally OR
19
+ // if the changeset is no longer in its initial pristine state.
20
+ hasValidated: or('_hasValidatedFlag', 'isChangesetAttempted'),
21
+ isChangesetAttempted: not('changeset.isPristine'),
22
+
14
23
  hasValidationErrors: notEmpty('validationErrors'),
15
24
  doesNotHaveValidationErrors: not('hasValidationErrors'),
16
25
  isValid: and('isNotValidating', 'hasValidated', 'doesNotHaveValidationErrors'),
17
26
  isInvalid: and('isNotValidating', 'hasValidated', 'hasValidationErrors'),
18
27
  changesetErrors: alias('changeset.error'),
19
28
 
20
- validationErrors: computed('changesetErrors', function() {
21
- const changesetErrors = this.get('changesetErrors');
22
- const property = this.get('property');
23
- const errors = get(changesetErrors, property);
24
-
25
- // filter out validations that are promises...
26
- // ember changeset seems to put the validation promise as the value for `validation`
27
- // before it resolves or rejects.
28
- if (!errors || typeof errors.validation === 'object' && errors.validation !== null && typeof errors.validation.then === 'function') {
29
- return;
30
- }
31
- return errors;
29
+ validationErrors: computed('changeset.error', 'property', function() {
30
+ return get(this.get('changeset.error'), this.get('property'));
32
31
  }),
33
32
 
34
33
  didReceiveAttrs() {
35
34
  this._super(...arguments);
36
-
37
35
  this.cleanUpObservers();
38
-
39
- let changeset = this.get('changeset');
40
- let property = this.get('property');
41
-
36
+ const changeset = this.get('changeset');
37
+ const property = this.get('property');
38
+
39
+ // Add observer for the property
42
40
  changeset.addObserver(property, this, 'valueDidChange');
43
- changeset.on('beforeValidation', this, 'beforeValidation');
44
- changeset.on('afterValidation', this, 'afterValidation');
45
-
46
- this._prev = { changeset, property };
41
+
42
+ // Listen for validation state changes on the changeset
43
+ if (changeset.validate) {
44
+ const originalValidate = changeset.validate;
45
+ changeset.validate = (...args) => {
46
+ this.set('isValidating', true);
47
+ const result = originalValidate.apply(changeset, args);
48
+
49
+ if (result && typeof result.then === 'function') {
50
+ return result
51
+ .then((validationResult) => {
52
+ if (!this.isDestroyed) {
53
+ this.set('isValidating', false);
54
+ this.set('_hasValidatedFlag', true);
55
+ this.notifyPropertyChange('validationErrors');
56
+ }
57
+ return validationResult;
58
+ })
59
+ .catch((error) => {
60
+ if (!this.isDestroyed) {
61
+ this.set('isValidating', false);
62
+ this.set('_hasValidatedFlag', true);
63
+ this.notifyPropertyChange('validationErrors');
64
+ }
65
+ throw error;
66
+ });
67
+ } else {
68
+ this.set('isValidating', false);
69
+ this.set('_hasValidatedFlag', true);
70
+ this.notifyPropertyChange('validationErrors');
71
+ return result;
72
+ }
73
+ };
74
+ }
75
+
76
+ this._prev = {
77
+ changeset,
78
+ property,
79
+ originalValidate: changeset.validate
80
+ };
47
81
  },
48
82
 
49
83
  willDestroyElement() {
84
+ // Set a flag to prevent any pending validations from updating state
85
+ this._isDestroyed = true;
50
86
  this.cleanUpObservers();
51
-
52
87
  this._super(...arguments);
53
88
  },
54
-
55
- beforeValidation(key) {
56
- if (key === this.property) {
57
- this.set('isValidating', true);
58
- }
89
+
90
+ willDestroy() {
91
+ this._isDestroyed = true;
92
+ this.cleanUpObservers();
93
+ this._super(...arguments);
59
94
  },
60
95
 
61
- afterValidation(key) {
62
- if (key === this.property) {
63
- this.set('hasValidated', true);
64
- this.set('isValidating', false);
96
+ cleanUpObservers() {
97
+ if (!this._prev) { return; }
98
+ const { changeset, property, originalValidate } = this._prev;
99
+ changeset.removeObserver(property, this, 'valueDidChange');
100
+
101
+ // Restore original validate function if we patched it
102
+ if (originalValidate && changeset.validate) {
103
+ changeset.validate = originalValidate;
65
104
  }
105
+
106
+ this._prev = null;
66
107
  },
67
108
 
68
109
  valueDidChange() {
110
+ if (this._isDestroyed) { return; }
69
111
  const newValue = this.get('changeset').get(this.get('property'));
70
-
71
112
  if (newValue === this._prevValue) { return; }
72
-
73
113
  this._prevValue = newValue;
74
114
  this.notifyPropertyChange('value');
75
115
  this.scheduleValidation();
76
116
  },
77
117
 
78
- cleanUpObservers() {
79
- if (!this._prev) { return; }
80
-
81
- let { changeset, property } = this._prev;
82
-
83
- changeset.removeObserver(property, this, 'valueDidChange');
84
- changeset.off('beforeValidation', this, 'beforeValidation');
85
- changeset.off('afterValidation', this, 'afterValidation');
86
-
87
- this._prev = null;
88
- },
89
-
90
118
  value: computed('changeset', 'property', {
91
- get(/* key */) {
92
- return this.get('changeset').get(this.get('property'));
119
+ get() {
120
+ const property = this.get('property');
121
+ // This getter now correctly establishes a dependency on the nested property
122
+ return this.get(`changeset.${property}`);
93
123
  },
94
124
  set(key, value) {
95
- // The `valueDidChange` observer is responsible for invoking
96
- // `scheduleValidation` in reaction to this change.
97
125
  this.get('changeset').set(this.get('property'), value);
98
126
  return value;
99
127
  }
@@ -105,10 +133,42 @@ export default Component.extend({
105
133
  },
106
134
 
107
135
  validateProperty() {
108
- if (!this.get('isDestroyed')) {
109
- const changeset = this.get('changeset');
110
- const property = this.get('property');
111
- return changeset.validate(property);
136
+ if (this.isDestroyed || this._isDestroyed) { return; }
137
+
138
+ // Manually setting the flag here ensures it's true even if debounce is 0
139
+ this.set('isValidating', true);
140
+ const changeset = this.get('changeset');
141
+ const property = this.get('property');
142
+ const maybePromise = changeset.validate(property);
143
+
144
+ const onFinally = (error) => {
145
+ if (this.isDestroyed) { return; }
146
+
147
+ this.set('_hasValidatedFlag', true);
148
+ this.set('isValidating', false);
149
+
150
+ // If there was an error, ensure the error is set on the changeset
151
+ if (error) {
152
+ const errorObj = {};
153
+ errorObj[property] = error.message || error;
154
+ changeset.set('error', { [property]: [errorObj] });
155
+ }
156
+
157
+ this.notifyPropertyChange('validationErrors');
158
+ };
159
+
160
+ if (maybePromise && typeof maybePromise.then === 'function') {
161
+ return maybePromise
162
+ .then(() => onFinally())
163
+ .catch(error => onFinally(error))
164
+ .finally(() => {
165
+ if (!this.isDestroyed) {
166
+ this.notifyPropertyChange('validationErrors');
167
+ }
168
+ });
169
+ } else {
170
+ onFinally();
171
+ return maybePromise;
112
172
  }
113
173
  }
114
- });
174
+ });
@@ -1,5 +1,6 @@
1
1
  import Component from '@ember/component';
2
2
  import { alias, bool } from '@ember/object/computed';
3
+ import { computed } from '@ember/object';
3
4
  import layout from '@heroku/ember-hk-components/templates/components/hk-validation-errors-list';
4
5
 
5
6
  export default Component.extend({
@@ -7,4 +8,7 @@ export default Component.extend({
7
8
  tagName: '',
8
9
  hasValidationErrors: bool('validationErrors'),
9
10
  validationErrorMessages: alias('validationErrors.validation'),
11
+ errorsListId: computed('property', function() {
12
+ return `validation-errors-${this.get('property')}`;
13
+ }),
10
14
  });
@@ -1,8 +1,8 @@
1
1
  {{yield (hash
2
- value=value
3
- isValidating=isValidating
4
- isValid=isValid
5
- isInvalid=isInvalid
6
- errors=validationErrors
7
- errorsList=(component 'hk-validation-errors-list' validationErrors=validationErrors property=property)
8
- )}}
2
+ value=this.value
3
+ isValidating=this.isValidating
4
+ isValid=this.isValid
5
+ isInvalid=this.isInvalid
6
+ errors=this.validationErrors
7
+ errorsList=(component 'hk-validation-errors-list' validationErrors=this.validationErrors property=this.property)
8
+ )}}