diff options
Diffstat (limited to 'doc/development/fe_guide/vue.md')
-rw-r--r-- | doc/development/fe_guide/vue.md | 82 |
1 files changed, 81 insertions, 1 deletions
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md index 220a4a107aa..574faa0898f 100644 --- a/doc/development/fe_guide/vue.md +++ b/doc/development/fe_guide/vue.md @@ -99,6 +99,86 @@ return new Vue({ > When adding an `id` attribute to mount a Vue application, please make sure this `id` is unique across the codebase. +#### Providing Rails form fields to Vue applications + +When composing a form with Rails, the `name`, `id`, and `value` attributes of form inputs are generated +to match the backend. It can be helpful to have access to these generated attributes when converting +a Rails form to Vue, or when [integrating components (datepicker, project selector, etc)](https://gitlab.com/gitlab-org/gitlab/-/blob/8956ad767d522f37a96e03840595c767de030968/app/assets/javascripts/access_tokens/index.js#L15) into it. +The [`parseRailsFormFields`](https://gitlab.com/gitlab-org/gitlab/-/blob/fe88797f682c7ff0b13f2c2223a3ff45ada751c1/app/assets/javascripts/lib/utils/forms.js#L107) utility can be used to parse the generated form input attributes so they can be passed to the Vue application. +This allows us to easily integrate Vue components without changing how the form submits. + +```haml +-# form.html.haml += form_for user do |form| + .js-user-form + = form.text_field :name, class: 'form-control gl-form-input', data: { js_name: 'name' } + = form.text_field :email, class: 'form-control gl-form-input', data: { js_name: 'email' } +``` + +> The `js_name` data attribute is used as the key in the resulting JavaScript object. +For example `= form.text_field :email, data: { js_name: 'fooBarBaz' }` would be translated +to `{ fooBarBaz: { name: 'user[email]', id: 'user_email', value: '' } }` + +```javascript +// index.js +import Vue from 'vue'; +import { parseRailsFormFields } from '~/lib/utils/forms'; +import UserForm from './components/user_form.vue'; + +export const initUserForm = () => { + const el = document.querySelector('.js-user-form'); + + if (!el) { + return null; + } + + const fields = parseRailsFormFields(el); + + return new Vue({ + el, + render(h) { + return h(UserForm, { + props: { + fields, + }, + }); + }, + }); +}; +``` + +```vue +<script> +// user_form.vue +import { GlButton, GlFormGroup, GlFormInput } from '@gitlab/ui'; + +export default { + name: 'UserForm', + components: { GlButton, GlFormGroup, GlFormInput }, + props: { + fields: { + type: Object, + required: true, + }, + }, +}; +</script> + +<template> + <div> + <gl-form-group :label-for="fields.name.id" :label="__('Name')"> + <gl-form-input v-bind="fields.name" size="lg" /> + </gl-form-group> + + <gl-form-group :label-for="fields.email.id" :label="__('Email')"> + <gl-form-input v-bind="fields.email" type="email" size="lg" /> + </gl-form-group> + + <gl-button type="submit" category="primary" variant="confirm">{{ __('Update') }}</gl-button> + </div> +</template> +``` + #### Accessing the `gl` object We query the `gl` object for data that doesn't change during the application's life @@ -197,7 +277,7 @@ Check this [page](vuex.md) for more details. In the [Vue documentation](https://vuejs.org/v2/api/#Options-Data) the Data function/object is defined as follows: > The data object for the Vue instance. Vue recursively converts its properties into getter/setters -to make it “reactive”. The object must be plain: native objects such as browser API objects and +to make it "reactive". The object must be plain: native objects such as browser API objects and prototype properties are ignored. A rule of thumb is that data should just be data - it is not recommended to observe objects with their own stateful behavior. |