diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-27 15:08:35 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-27 15:08:35 +0300 |
commit | 22e9af3c8b8aedf7f46b786be968862b74a2d07e (patch) | |
tree | a10a7d9af40a17fe6cda7b3a681f5e5e2112c16e /doc/development | |
parent | c8e28a0bb8dd45d91cb72ff2c930bc4a562f1fc7 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'doc/development')
-rw-r--r-- | doc/development/fe_guide/vuex.md | 90 | ||||
-rw-r--r-- | doc/development/testing_guide/best_practices.md | 20 |
2 files changed, 102 insertions, 8 deletions
diff --git a/doc/development/fe_guide/vuex.md b/doc/development/fe_guide/vuex.md index 20abf4fcb3e..0bb9e3b7d50 100644 --- a/doc/development/fe_guide/vuex.md +++ b/doc/development/fe_guide/vuex.md @@ -396,3 +396,93 @@ export default () => {}; ``` [vuex-docs]: https://vuex.vuejs.org + +### Two way data binding + +When storing form data in Vuex, it is sometimes necessary to update the value stored. The store should never be mutated directly, and an action should be used instead. +In order to still use `v-model` in our code, we need to create computed properties in this form: + +```javascript +export default { + computed: { + someValue: { + get() { + return this.$store.state.someValue; + }, + set(value) { + this.$store.dispatch("setSomeValue", value); + } + } + } +}; +``` + +An alternative is to use `mapState` and `mapActions`: + +```javascript +export default { + computed: { + ...mapState(['someValue']), + localSomeValue: { + get() { + return this.someValue; + }, + set(value) { + this.setSomeValue(value) + } + } + }, + methods: { + ...mapActions(['setSomeValue']) + } +}; +``` + +Adding a few of these properties becomes cumbersome, and makes the code more repetitive with more tests to write. To simplify this there is a helper in `~/vuex_shared/bindings.js` + +The helper can be used like so: + +```javascript +// this store is non-functional and only used to give context to the example +export default { + state: { + baz: '', + bar: '', + foo: '' + }, + actions: { + updateBar() {...} + updateAll() {...} + }, + getters: { + getFoo() {...} + } +} +``` + +```javascript +import { mapComputed } from '~/vuex_shared/bindings' +export default { + computed: { + /** + * @param {(string[]|Object[])} list - list of string matching state keys or list objects + * @param {string} list[].key - the key matching the key present in the vuex state + * @param {string} list[].getter - the name of the getter, leave it empty to not use a getter + * @param {string} list[].updateFn - the name of the action, leave it empty to use the default action + * @param {string} defaultUpdateFn - the default function to dispatch + * @param {string} root - optional key of the state where to search fo they keys described in list + * @returns {Object} a dictionary with all the computed properties generated + */ + ...mapComputed( + [ + 'baz', + { key: 'bar', updateFn: 'updateBar' } + { key: 'foo', getter: 'getFoo' }, + ], + 'updateAll', + ), + } +} +``` + +`mapComputed` will then generate the appropriate computed properties that get the data from the store and dispatch the correct action when updated. diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md index a845b5a26e8..78702ce173c 100644 --- a/doc/development/testing_guide/best_practices.md +++ b/doc/development/testing_guide/best_practices.md @@ -532,20 +532,24 @@ This is especially useful whenever it's showing 500 internal server error. ### Shared contexts -All shared contexts should be placed under `spec/support/shared_contexts/`. -Shared contexts can be placed in subfolder if they apply to a certain type of -specs only (e.g. features, requests etc.) but shouldn't be if they apply to -multiple type of specs. +Shared contexts only used in one spec file can be declared inline. +Any shared contexts used by more than one spec file: + +- Should be placed under `spec/support/shared_contexts/`. +- Can be placed in subfolder if they apply to a certain type of specs only + (e.g. features, requests etc.) but shouldn't be if they apply to multiple type of specs. Each file should include only one context and have a descriptive name, e.g. `spec/support/shared_contexts/controllers/githubish_import_controller_shared_context.rb`. ### Shared examples -All shared examples should be placed under `spec/support/shared_examples/`. -Shared examples can be placed in subfolder if they apply to a certain type of -specs only (e.g. features, requests etc.) but shouldn't be if they apply to -multiple type of specs. +Shared examples only used in one spec file can be declared inline. +Any shared examples used by more than one spec file: + +- Should be placed under `spec/support/shared_examples/`. +- Can be placed in subfolder if they apply to a certain type of specs only + (e.g. features, requests etc.) but shouldn't be if they apply to multiple type of specs. Each file should include only one context and have a descriptive name, e.g. `spec/support/shared_examples/controllers/githubish_import_controller_shared_example.rb`. |