@awes-io/ui 2.142.3 → 2.144.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.
Files changed (264) hide show
  1. package/assets/css/components/_index.css +7 -1
  2. package/assets/css/components/action-card.css +1 -0
  3. package/assets/css/components/action-icon.css +2 -2
  4. package/assets/css/components/alert.css +28 -22
  5. package/assets/css/components/animation.css +52 -32
  6. package/assets/css/components/badge.css +1 -0
  7. package/assets/css/components/banner-text.css +15 -4
  8. package/assets/css/components/card.css +0 -1
  9. package/assets/css/components/content-placeholder.css +104 -0
  10. package/assets/css/components/dropdown.css +20 -7
  11. package/assets/css/components/empty-container.css +69 -1
  12. package/assets/css/components/filter-chosen.css +6 -0
  13. package/assets/css/components/filter-date-range.css +17 -1
  14. package/assets/css/components/filter-month.css +23 -17
  15. package/assets/css/components/filter-select.css +11 -0
  16. package/assets/css/components/icon-menu-item.css +12 -7
  17. package/assets/css/components/layout.css +1 -32
  18. package/assets/css/components/mobile-menu-nav.css +8 -4
  19. package/assets/css/components/modal.css +1 -1
  20. package/assets/css/components/number.css +12 -0
  21. package/assets/css/components/page-aside.css +54 -0
  22. package/assets/css/components/text-field.css +4 -0
  23. package/assets/js/css.js +1 -1
  24. package/assets/js/icons/mono.js +59 -91
  25. package/assets/js/icons/multicolor.js +1 -31
  26. package/components/1_atoms/AwActionIcon.vue +11 -2
  27. package/components/1_atoms/AwContentPlaceholder.vue +60 -0
  28. package/components/1_atoms/AwFlow.vue +37 -49
  29. package/components/1_atoms/AwGrid.vue +11 -3
  30. package/components/1_atoms/AwIcon/AwIcon.vue +5 -3
  31. package/components/1_atoms/AwIcon/AwIconSystemMono.vue +3 -2
  32. package/components/1_atoms/AwInput.vue +2 -2
  33. package/components/1_atoms/AwLabel.vue +1 -1
  34. package/components/1_atoms/AwList.vue +3 -1
  35. package/components/1_atoms/AwRadio.vue +1 -1
  36. package/components/1_atoms/AwSlider.vue +15 -1
  37. package/components/1_atoms/AwTag.vue +6 -1
  38. package/components/2_molecules/AwAlert.vue +63 -42
  39. package/components/2_molecules/AwBadge.vue +1 -1
  40. package/components/2_molecules/AwBannerText.vue +8 -2
  41. package/components/2_molecules/AwButton.vue +1 -1
  42. package/components/2_molecules/AwDescriptionInput.vue +19 -1
  43. package/components/2_molecules/AwEmptyContainer.vue +74 -72
  44. package/components/2_molecules/AwNumber.vue +180 -0
  45. package/components/2_molecules/AwSelect.vue +11 -4
  46. package/components/3_organisms/AwBottomBar.vue +22 -4
  47. package/components/3_organisms/AwFilterChosen.vue +73 -0
  48. package/components/3_organisms/AwFilterDateRange.vue +177 -0
  49. package/components/3_organisms/AwFilterMonth.vue +37 -40
  50. package/components/3_organisms/AwFilterSelect.vue +368 -0
  51. package/components/3_organisms/AwMultiBlockBuilder.vue +1 -1
  52. package/components/3_organisms/AwSubnav.vue +11 -1
  53. package/components/3_organisms/AwTable/AwTableBuilder.vue +20 -60
  54. package/components/3_organisms/AwTable/_AwTableCellDropdown.vue +6 -1
  55. package/components/3_organisms/AwTable/_AwTableRow.vue +2 -1
  56. package/components/4_pages/AwPage.vue +1 -0
  57. package/components/4_pages/AwPageAside.vue +108 -0
  58. package/components/5_layouts/AwLayoutCenter.vue +3 -8
  59. package/components/5_layouts/_AwMenuItemIcon.vue +9 -2
  60. package/components/5_layouts/_AwMobileMenuItem.vue +5 -3
  61. package/components/5_layouts/_AwUserMenu.vue +1 -1
  62. package/components/_config.js +26 -1
  63. package/docs/_template.md +80 -0
  64. package/docs/components/atoms/aw-accordion-fold.md +129 -0
  65. package/docs/components/atoms/aw-action-card-body.md +99 -0
  66. package/docs/components/atoms/aw-action-card.md +130 -0
  67. package/docs/components/atoms/aw-action-icon.md +126 -0
  68. package/docs/components/atoms/aw-avatar.md +106 -0
  69. package/docs/components/atoms/aw-card.md +137 -0
  70. package/docs/components/atoms/aw-checkbox.md +288 -0
  71. package/docs/components/atoms/aw-content-placeholder.md +147 -0
  72. package/docs/components/atoms/aw-description.md +83 -0
  73. package/docs/components/atoms/aw-dock.md +90 -0
  74. package/docs/components/atoms/aw-dropdown-button.md +94 -0
  75. package/docs/components/atoms/aw-dropdown.md +178 -0
  76. package/docs/components/atoms/aw-file.md +73 -0
  77. package/docs/components/atoms/aw-flow.md +140 -0
  78. package/docs/components/atoms/aw-grid.md +109 -0
  79. package/docs/components/atoms/aw-headline.md +71 -0
  80. package/docs/components/atoms/aw-icon-system-color.md +122 -0
  81. package/docs/components/atoms/aw-icon-system-mono.md +206 -0
  82. package/docs/components/atoms/aw-icon.md +235 -0
  83. package/docs/components/atoms/aw-info.md +123 -0
  84. package/docs/components/atoms/aw-input.md +212 -0
  85. package/docs/components/atoms/aw-label.md +136 -0
  86. package/docs/components/atoms/aw-link.md +151 -0
  87. package/docs/components/atoms/aw-list.md +152 -0
  88. package/docs/components/atoms/aw-progress.md +119 -0
  89. package/docs/components/atoms/aw-radio.md +182 -0
  90. package/docs/components/atoms/aw-refresh-wrapper.md +81 -0
  91. package/docs/components/atoms/aw-select-native.md +234 -0
  92. package/docs/components/atoms/aw-slider.md +189 -0
  93. package/docs/components/atoms/aw-sub-headline.md +73 -0
  94. package/docs/components/atoms/aw-switcher.md +192 -0
  95. package/docs/components/atoms/aw-tag.md +144 -0
  96. package/docs/components/atoms/aw-title.md +70 -0
  97. package/docs/components/atoms/aw-toggler.md +90 -0
  98. package/docs/components/layouts/aw-layout-center.md +168 -0
  99. package/docs/components/layouts/aw-layout-error.md +153 -0
  100. package/docs/components/layouts/aw-layout-provider.md +238 -0
  101. package/docs/components/layouts/aw-layout.md +88 -0
  102. package/docs/components/molecules/aw-action-button.md +138 -0
  103. package/docs/components/molecules/aw-alert.md +191 -0
  104. package/docs/components/molecules/aw-badge.md +129 -0
  105. package/docs/components/molecules/aw-banner-text.md +156 -0
  106. package/docs/components/molecules/aw-button-nav.md +111 -0
  107. package/docs/components/molecules/aw-button.md +193 -0
  108. package/docs/components/molecules/aw-description-input.md +124 -0
  109. package/docs/components/molecules/aw-empty-container.md +235 -0
  110. package/docs/components/molecules/aw-island.md +506 -0
  111. package/docs/components/molecules/aw-number.md +138 -0
  112. package/docs/components/molecules/aw-select-object.md +401 -0
  113. package/docs/components/molecules/aw-select.md +215 -0
  114. package/docs/components/molecules/aw-tab-nav.md +108 -0
  115. package/docs/components/molecules/aw-tel.md +129 -0
  116. package/docs/components/molecules/aw-textarea.md +83 -0
  117. package/docs/components/molecules/aw-userpic.md +115 -0
  118. package/docs/components/organisms/aw-address-block.md +64 -0
  119. package/docs/components/organisms/aw-address.md +132 -0
  120. package/docs/components/organisms/aw-birthday-picker.md +73 -0
  121. package/docs/components/organisms/aw-bottom-bar.md +66 -0
  122. package/docs/components/organisms/aw-calendar-days.md +115 -0
  123. package/docs/components/organisms/aw-calendar-nav.md +98 -0
  124. package/docs/components/organisms/aw-calendar-view.md +98 -0
  125. package/docs/components/organisms/aw-calendar.md +166 -0
  126. package/docs/components/organisms/aw-chart.md +154 -0
  127. package/docs/components/organisms/aw-chip-select.md +164 -0
  128. package/docs/components/organisms/aw-chip.md +126 -0
  129. package/docs/components/organisms/aw-code-snippet.md +94 -0
  130. package/docs/components/organisms/aw-code.md +132 -0
  131. package/docs/components/organisms/aw-context-menu.md +117 -0
  132. package/docs/components/organisms/aw-cropper.md +151 -0
  133. package/docs/components/organisms/aw-date.md +161 -0
  134. package/docs/components/organisms/aw-display-date.md +33 -0
  135. package/docs/components/organisms/aw-download-link.md +46 -0
  136. package/docs/components/organisms/aw-fetch-data.md +161 -0
  137. package/docs/components/organisms/aw-filter-chosen.md +226 -0
  138. package/docs/components/organisms/aw-filter-date-range.md +205 -0
  139. package/docs/components/organisms/aw-filter-month.md +43 -0
  140. package/docs/components/organisms/aw-filter-select.md +239 -0
  141. package/docs/components/organisms/aw-form.md +174 -0
  142. package/docs/components/organisms/aw-gmap-marker.md +86 -0
  143. package/docs/components/organisms/aw-gmap.md +90 -0
  144. package/docs/components/organisms/aw-image-upload.md +56 -0
  145. package/docs/components/organisms/aw-island-avatar.md +87 -0
  146. package/docs/components/organisms/aw-markdown-editor.md +104 -0
  147. package/docs/components/organisms/aw-modal-buttons.md +57 -0
  148. package/docs/components/organisms/aw-modal.md +246 -0
  149. package/docs/components/organisms/aw-model-edit.md +74 -0
  150. package/docs/components/organisms/aw-money.md +53 -0
  151. package/docs/components/organisms/aw-multi-block-builder.md +165 -0
  152. package/docs/components/organisms/aw-pagination.md +121 -0
  153. package/docs/components/organisms/aw-password.md +103 -0
  154. package/docs/components/organisms/aw-preview-card.md +45 -0
  155. package/docs/components/organisms/aw-search.md +116 -0
  156. package/docs/components/organisms/aw-subnav.md +122 -0
  157. package/docs/components/organisms/aw-table-builder.md +165 -0
  158. package/docs/components/organisms/aw-table-col.md +123 -0
  159. package/docs/components/organisms/aw-table-head.md +92 -0
  160. package/docs/components/organisms/aw-table-row.md +91 -0
  161. package/docs/components/organisms/aw-table.md +172 -0
  162. package/docs/components/organisms/aw-tags.md +54 -0
  163. package/docs/components/organisms/aw-toggle-show-aside.md +43 -0
  164. package/docs/components/organisms/aw-uploader-files.md +125 -0
  165. package/docs/components/organisms/aw-uploader.md +163 -0
  166. package/docs/components/organisms/aw-user-menu.md +87 -0
  167. package/docs/components/pages/aw-page-aside.md +296 -0
  168. package/docs/components/pages/aw-page-menu-buttons.md +172 -0
  169. package/docs/components/pages/aw-page-modal.md +198 -0
  170. package/docs/components/pages/aw-page-single.md +300 -0
  171. package/docs/components/pages/aw-page.md +194 -0
  172. package/docs/configuration.md +493 -0
  173. package/docs/cookbook/advanced-patterns.md +1388 -0
  174. package/docs/cookbook/common-patterns.md +965 -0
  175. package/docs/cookbook/index.md +786 -0
  176. package/docs/getting-started.md +596 -0
  177. package/docs/guides/best-practices.md +1106 -0
  178. package/docs/guides/data-fetching.md +852 -0
  179. package/docs/guides/error-handling.md +1172 -0
  180. package/docs/guides/forms-guide.md +1329 -0
  181. package/docs/guides/mobile-subnavigation.md +359 -0
  182. package/docs/guides/page-patterns/aside-pages.md +1418 -0
  183. package/docs/guides/page-patterns/dashboard-pages.md +990 -0
  184. package/docs/guides/page-patterns/detail-pages.md +1556 -0
  185. package/docs/guides/page-patterns/list-pages.md +1242 -0
  186. package/docs/index.md +263 -1
  187. package/docs/integrations.md +870 -0
  188. package/docs/reference/colors.md +232 -0
  189. package/docs/reference/icons.md +163 -0
  190. package/docs/reference/menu.md +462 -0
  191. package/docs/reference/plugins.md +970 -0
  192. package/docs/reference/troubleshooting.md +964 -0
  193. package/nuxt/awes.config.js +9 -8
  194. package/nuxt/index.js +2 -2
  195. package/nuxt/pages/more.vue +1 -1
  196. package/package.json +5 -3
  197. package/readme.md +171 -1
  198. package/store/awesIo.js +11 -0
  199. package/CHANGELOG.md +0 -4520
  200. package/docs/aw-accordion-fold.md +0 -46
  201. package/docs/aw-address.md +0 -44
  202. package/docs/aw-avatar.md +0 -51
  203. package/docs/aw-badge.md +0 -32
  204. package/docs/aw-button-nav.md +0 -44
  205. package/docs/aw-button.md +0 -50
  206. package/docs/aw-calendar-days.md +0 -46
  207. package/docs/aw-calendar-nav.md +0 -25
  208. package/docs/aw-calendar-view.md +0 -12
  209. package/docs/aw-calendar.md +0 -59
  210. package/docs/aw-card.md +0 -48
  211. package/docs/aw-chart.md +0 -51
  212. package/docs/aw-checkbox.md +0 -56
  213. package/docs/aw-chip-select.md +0 -46
  214. package/docs/aw-chip.md +0 -53
  215. package/docs/aw-code-snippet.md +0 -18
  216. package/docs/aw-code.md +0 -56
  217. package/docs/aw-content-wrapper.md +0 -40
  218. package/docs/aw-context-menu.md +0 -31
  219. package/docs/aw-cropper.md +0 -60
  220. package/docs/aw-dashboard-card.md +0 -37
  221. package/docs/aw-dashboard-donut.md +0 -30
  222. package/docs/aw-dashboard-line.md +0 -20
  223. package/docs/aw-dashboard-progress.md +0 -33
  224. package/docs/aw-dashboard-section.md +0 -32
  225. package/docs/aw-dashboard-speed.md +0 -30
  226. package/docs/aw-date.md +0 -52
  227. package/docs/aw-dropdown-button.md +0 -31
  228. package/docs/aw-dropdown.md +0 -69
  229. package/docs/aw-fetch-data.md +0 -45
  230. package/docs/aw-form.md +0 -52
  231. package/docs/aw-grid.md +0 -48
  232. package/docs/aw-icon.md +0 -50
  233. package/docs/aw-info.md +0 -53
  234. package/docs/aw-input.md +0 -55
  235. package/docs/aw-layout-default.md +0 -30
  236. package/docs/aw-layout-frame-center.md +0 -29
  237. package/docs/aw-layout-simple.md +0 -49
  238. package/docs/aw-link.md +0 -54
  239. package/docs/aw-markdown-editor.md +0 -51
  240. package/docs/aw-modal.md +0 -63
  241. package/docs/aw-multi-block-builder.md +0 -66
  242. package/docs/aw-page.md +0 -36
  243. package/docs/aw-pagination.md +0 -54
  244. package/docs/aw-password.md +0 -48
  245. package/docs/aw-radio.md +0 -54
  246. package/docs/aw-search.md +0 -49
  247. package/docs/aw-select.md +0 -93
  248. package/docs/aw-slider.md +0 -40
  249. package/docs/aw-svg-image.md +0 -19
  250. package/docs/aw-switcher.md +0 -51
  251. package/docs/aw-tab-nav.md +0 -55
  252. package/docs/aw-table-builder.md +0 -58
  253. package/docs/aw-table-col.md +0 -33
  254. package/docs/aw-table-head.md +0 -28
  255. package/docs/aw-table-row.md +0 -33
  256. package/docs/aw-table.md +0 -59
  257. package/docs/aw-tel.md +0 -47
  258. package/docs/aw-textarea.md +0 -47
  259. package/docs/aw-toggler.md +0 -41
  260. package/docs/aw-uploader-files.md +0 -20
  261. package/docs/aw-uploader.md +0 -60
  262. package/docs/aw-user-menu.md +0 -34
  263. package/docs/aw-userpic.md +0 -34
  264. /package/components/{3_organisms → 2_molecules}/AwTel.vue +0 -0
@@ -0,0 +1,1329 @@
1
+ ---
2
+ metaTitle: Forms Integration Guide | AwesCode UI
3
+ meta:
4
+ - name: description
5
+ content: Complete guide to building forms with AwesCode UI components - validation, error handling, and common patterns.
6
+ title: Forms Integration Guide
7
+ ---
8
+
9
+ # Forms Integration Guide
10
+
11
+ Complete guide to building forms with AwesCode UI components.
12
+
13
+ ## Table of Contents
14
+
15
+ - [Model-Based Forms (Recommended)](#model-based-forms-recommended)
16
+ - [Basic Form Structure](#basic-form-structure)
17
+ - [Form Inputs](#form-inputs)
18
+ - [Validation & Errors](#validation--errors)
19
+ - [File Uploads](#file-uploads)
20
+ - [Complex Forms](#complex-forms)
21
+ - [Modal Forms](#modal-forms)
22
+ - [Multi-Step Forms](#multi-step-forms)
23
+ - [Best Practices](#best-practices)
24
+
25
+ ## Model-Based Forms (Recommended)
26
+
27
+ For CRUD operations and data editing, use `AwModelEdit` with Vue-MC models instead of raw `AwForm`. This provides automatic change detection, validation, error handling, and state management.
28
+
29
+ ### Why Use AwModelEdit?
30
+
31
+ **AwModelEdit** wraps your form fields and provides:
32
+ - Automatic change detection with unsaved changes warning
33
+ - Save/Cancel buttons that appear when data changes
34
+ - Keyboard shortcuts (Ctrl+Enter to save, Escape to cancel)
35
+ - Automatic error scrolling to first invalid field
36
+ - Sticky action panel that follows scroll
37
+ - Integration with Vue-MC model lifecycle
38
+
39
+ **Use AwModelEdit when:**
40
+ - Editing database records (users, posts, settings, etc.)
41
+ - Need change detection and confirmation dialogs
42
+ - Working with complex nested data structures
43
+ - Need automatic state management
44
+ - Server-side validation with field-level errors
45
+
46
+ **Use AwForm when:**
47
+ - One-off operations (login, contact forms, search)
48
+ - Simple data submission without persistent state
49
+ - File uploads to specific endpoints
50
+ - Custom form handling logic needed
51
+
52
+ ### Simple Edit Form
53
+
54
+ ```markup
55
+ <template>
56
+ <AwPage :title="title">
57
+ <AwContentPlaceholder v-if="user.fetching" type="form" :lines="4" />
58
+
59
+ <AwModelEdit v-else :model="user">
60
+ <AwGrid>
61
+ <AwCard title="Profile Information">
62
+ <AwInput
63
+ v-model="user.email"
64
+ :error="user.errors.email"
65
+ label="Email"
66
+ />
67
+
68
+ <AwInput
69
+ v-model="user.first_name"
70
+ :error="user.errors.first_name"
71
+ label="First Name"
72
+ />
73
+
74
+ <AwInput
75
+ v-model="user.last_name"
76
+ :error="user.errors.last_name"
77
+ label="Last Name"
78
+ />
79
+ </AwCard>
80
+ </AwGrid>
81
+ </AwModelEdit>
82
+ </AwPage>
83
+ </template>
84
+
85
+ <script>
86
+ import User from '@/models/User'
87
+
88
+ export default {
89
+ data() {
90
+ return {
91
+ user: new User({ id: this.$route.params.id })
92
+ }
93
+ },
94
+
95
+ computed: {
96
+ title() {
97
+ return this.user.isNew() ? 'Create User' : `Edit ${this.user.first_name}`
98
+ }
99
+ },
100
+
101
+ fetch() {
102
+ // Load existing user data
103
+ return this.user.isNew()
104
+ ? Promise.resolve()
105
+ : this.user.fetch()
106
+ }
107
+ }
108
+ </script>
109
+ ```
110
+
111
+ ### Defining Vue-MC Models
112
+
113
+ ```javascript
114
+ // models/User.js
115
+ import { BaseModel } from '@awes-io/vue-mc'
116
+
117
+ export default class User extends BaseModel {
118
+ defaults() {
119
+ return {
120
+ id: null,
121
+ email: '',
122
+ first_name: '',
123
+ last_name: '',
124
+ status: 'active',
125
+ role: {
126
+ id: null,
127
+ name: ''
128
+ }
129
+ }
130
+ }
131
+
132
+ routes() {
133
+ return {
134
+ fetch: '/api/users/{id}',
135
+ save: '/api/users', // POST for new
136
+ update: '/api/users/{id}', // PUT/PATCH for existing
137
+ delete: '/api/users/{id}' // DELETE
138
+ }
139
+ }
140
+
141
+ validation() {
142
+ return {
143
+ email: 'required|email',
144
+ first_name: 'required|min:2',
145
+ last_name: 'required|min:2'
146
+ }
147
+ }
148
+
149
+ // Computed properties
150
+ get full_name() {
151
+ return `${this.first_name} ${this.last_name}`.trim()
152
+ }
153
+ }
154
+ ```
155
+
156
+ ### Nested Data Structures
157
+
158
+ ```markup
159
+ <template>
160
+ <AwModelEdit :model="company">
161
+ <AwCard title="Company Details">
162
+ <AwInput
163
+ v-model="company.name"
164
+ :error="company.errors.name"
165
+ label="Company Name"
166
+ />
167
+
168
+ <AwInput
169
+ v-model="company.tax_id"
170
+ :error="company.errors.tax_id"
171
+ label="Tax ID"
172
+ />
173
+ </AwCard>
174
+
175
+ <AwCard title="Primary Contact">
176
+ <AwInput
177
+ v-model="company.contact.name"
178
+ :error="company.errors['contact.name']"
179
+ label="Contact Name"
180
+ />
181
+
182
+ <AwInput
183
+ v-model="company.contact.email"
184
+ :error="company.errors['contact.email']"
185
+ label="Contact Email"
186
+ type="email"
187
+ />
188
+
189
+ <AwTel
190
+ v-model="company.contact.phone"
191
+ :error="company.errors['contact.phone']"
192
+ label="Phone"
193
+ />
194
+ </AwCard>
195
+
196
+ <AwCard title="Address">
197
+ <AwAddress
198
+ v-model="company.address"
199
+ :error="company.errors.address"
200
+ :with-google-maps="true"
201
+ />
202
+ </AwCard>
203
+ </AwModelEdit>
204
+ </template>
205
+
206
+ <script>
207
+ import Company from '@/models/Company'
208
+
209
+ export default {
210
+ data() {
211
+ return {
212
+ company: new Company({ id: this.$route.params.id })
213
+ }
214
+ },
215
+
216
+ fetch() {
217
+ return this.company.isNew() ? Promise.resolve() : this.company.fetch()
218
+ }
219
+ }
220
+ </script>
221
+ ```
222
+
223
+ ### Custom Save Actions
224
+
225
+ ```markup
226
+ <template>
227
+ <AwModelEdit
228
+ :model="post"
229
+ @saved="onSaved"
230
+ >
231
+ <AwInput v-model="post.title" :error="post.errors.title" label="Title" />
232
+ <AwTextarea v-model="post.content" :error="post.errors.content" label="Content" />
233
+
234
+ <template #after-buttons>
235
+ <!-- Additional action buttons -->
236
+ <AwButton @click="publishPost" theme="outline" color="success">
237
+ Publish
238
+ </AwButton>
239
+
240
+ <AwButton @click="deletePost" theme="outline" color="error">
241
+ Delete
242
+ </AwButton>
243
+ </template>
244
+ </AwModelEdit>
245
+ </template>
246
+
247
+ <script>
248
+ export default {
249
+ data() {
250
+ return {
251
+ post: new Post({ id: this.$route.params.id })
252
+ }
253
+ },
254
+
255
+ methods: {
256
+ onSaved(post) {
257
+ this.$notify({ title: 'Post saved successfully!' })
258
+ // Custom redirect
259
+ if (post.isNew()) {
260
+ this.$router.push(`/posts/${post.id}/edit`)
261
+ }
262
+ },
263
+
264
+ async publishPost() {
265
+ try {
266
+ await this.post.save({ status: 'published' })
267
+ this.$notify({ title: 'Post published!' })
268
+ } catch (error) {
269
+ this.$notify({
270
+ type: 'error',
271
+ title: 'Failed to publish post'
272
+ })
273
+ }
274
+ },
275
+
276
+ async deletePost() {
277
+ if (confirm('Are you sure you want to delete this post?')) {
278
+ await this.post.delete()
279
+ this.$router.push('/posts')
280
+ }
281
+ }
282
+ }
283
+ }
284
+ </script>
285
+ ```
286
+
287
+ ### Conditional Fields
288
+
289
+ ```markup
290
+ <template>
291
+ <AwModelEdit :model="user">
292
+ <AwCard title="Account">
293
+ <AwInput v-model="user.email" :error="user.errors.email" label="Email" />
294
+
295
+ <!-- Show password field only for new users -->
296
+ <template v-if="user.isNew()">
297
+ <AwPassword
298
+ v-model="user.password"
299
+ :error="user.errors.password"
300
+ label="Password"
301
+ required
302
+ />
303
+
304
+ <AwPassword
305
+ v-model="user.password_confirmation"
306
+ :error="user.errors.password_confirmation"
307
+ label="Confirm Password"
308
+ required
309
+ />
310
+ </template>
311
+
312
+ <!-- Show reset button for existing users -->
313
+ <template v-else>
314
+ <AwButton @click="sendPasswordReset" theme="outline">
315
+ Send Password Reset Email
316
+ </AwButton>
317
+ </template>
318
+ </AwCard>
319
+
320
+ <AwCard title="Role & Status">
321
+ <!-- Show different options based on user permissions -->
322
+ <AwSelect
323
+ v-if="$can('manage-roles')"
324
+ v-model="user.role_id"
325
+ :error="user.errors.role_id"
326
+ :options="roles"
327
+ label="Role"
328
+ />
329
+
330
+ <AwSwitcher
331
+ v-model="user.is_active"
332
+ :error="user.errors.is_active"
333
+ label="Active Status"
334
+ />
335
+ </AwCard>
336
+ </AwModelEdit>
337
+ </template>
338
+ ```
339
+
340
+ ### Relationship Management
341
+
342
+ ```markup
343
+ <template>
344
+ <AwModelEdit :model="role">
345
+ <AwCard title="Role Information">
346
+ <AwInput
347
+ v-model="role.name"
348
+ :error="role.errors.name"
349
+ label="Role Name"
350
+ />
351
+
352
+ <AwTextarea
353
+ v-model="role.description"
354
+ :error="role.errors.description"
355
+ label="Description"
356
+ />
357
+ </AwCard>
358
+
359
+ <AwCard title="Permissions">
360
+ <!-- Many-to-many relationship with checkboxes -->
361
+ <AwCheckbox
362
+ v-for="permission in permissions.models"
363
+ :key="permission.id"
364
+ v-model="role.permission_ids"
365
+ :value="permission.id"
366
+ :label="permission.name"
367
+ >
368
+ {{ permission.name }}
369
+ <small class="text-muted">{{ permission.description }}</small>
370
+ </AwCheckbox>
371
+ </AwCard>
372
+ </AwModelEdit>
373
+ </template>
374
+
375
+ <script>
376
+ import Role from '@/models/Role'
377
+ import Permissions from '@/collections/Permissions'
378
+
379
+ export default {
380
+ data() {
381
+ return {
382
+ role: new Role({ id: this.$route.params.id }),
383
+ permissions: new Permissions()
384
+ }
385
+ },
386
+
387
+ async fetch() {
388
+ // Load permissions first, then role
389
+ await this.permissions.fetch()
390
+
391
+ if (!this.role.isNew()) {
392
+ await this.role.fetch()
393
+ }
394
+ }
395
+ }
396
+ </script>
397
+ ```
398
+
399
+ ### Advanced Configuration
400
+
401
+ ```markup
402
+ <template>
403
+ <AwModelEdit
404
+ :model="settings"
405
+ :saveText="$t('Save Changes')"
406
+ :cancelText="$t('Reset')"
407
+ :isNotify="true"
408
+ :notifyText="$t('Settings updated successfully')"
409
+ :isRedirect="false"
410
+ :saveMethod="customSave"
411
+ :alwaysVisible="true"
412
+ saveErrorPath="response.data.message"
413
+ @saved="onSettingsSaved"
414
+ @error="onError"
415
+ >
416
+ <!-- Form fields -->
417
+ </AwModelEdit>
418
+ </template>
419
+
420
+ <script>
421
+ export default {
422
+ data() {
423
+ return {
424
+ settings: new Settings({ id: 1 })
425
+ }
426
+ },
427
+
428
+ methods: {
429
+ async customSave() {
430
+ // Custom save logic
431
+ return this.settings.save({
432
+ validate: true,
433
+ additional_data: this.getAdditionalData()
434
+ })
435
+ },
436
+
437
+ onSettingsSaved(settings) {
438
+ // Reload app config
439
+ this.$store.dispatch('loadSettings')
440
+ },
441
+
442
+ onError(error) {
443
+ console.error('Save failed:', error)
444
+ this.$notify({
445
+ type: 'error',
446
+ title: 'Error',
447
+ message: error.response?.data?.message || 'Failed to save settings'
448
+ })
449
+ }
450
+ }
451
+ }
452
+ </script>
453
+ ```
454
+
455
+ ### Modal Forms with Models
456
+
457
+ ```markup
458
+ <template>
459
+ <div>
460
+ <AwButton @click="openModal">Create User</AwButton>
461
+
462
+ <AwModal :show="showModal" @close="closeModal">
463
+ <template #title>
464
+ {{ user.isNew() ? 'Create User' : 'Edit User' }}
465
+ </template>
466
+
467
+ <AwModelEdit
468
+ :model="user"
469
+ :isRedirect="false"
470
+ @saved="onUserSaved"
471
+ >
472
+ <AwInput v-model="user.email" :error="user.errors.email" label="Email" />
473
+ <AwInput v-model="user.first_name" :error="user.errors.first_name" label="First Name" />
474
+ <AwInput v-model="user.last_name" :error="user.errors.last_name" label="Last Name" />
475
+ </AwModelEdit>
476
+ </AwModal>
477
+ </div>
478
+ </template>
479
+
480
+ <script>
481
+ import User from '@/models/User'
482
+
483
+ export default {
484
+ data() {
485
+ return {
486
+ showModal: false,
487
+ user: null
488
+ }
489
+ },
490
+
491
+ methods: {
492
+ openModal(userId = null) {
493
+ this.user = new User(userId ? { id: userId } : {})
494
+
495
+ if (userId) {
496
+ this.user.fetch().then(() => {
497
+ this.showModal = true
498
+ })
499
+ } else {
500
+ this.showModal = true
501
+ }
502
+ },
503
+
504
+ closeModal() {
505
+ this.showModal = false
506
+ this.user = null
507
+ },
508
+
509
+ onUserSaved(user) {
510
+ this.$notify({ title: 'User saved successfully!' })
511
+ this.closeModal()
512
+ // Refresh list or take other action
513
+ this.$emit('user-saved', user)
514
+ }
515
+ }
516
+ }
517
+ </script>
518
+ ```
519
+
520
+ ## Basic Form Structure
521
+
522
+ > **Note:** For CRUD operations and data editing, use [AwModelEdit](#model-based-forms-recommended) instead. `AwForm` is best for one-off operations like login, search, and contact forms where you need raw HTTP form submission.
523
+
524
+ ### Simple Login Form
525
+
526
+ ```markup
527
+ <template>
528
+ <AwForm
529
+ url="/api/login"
530
+ method="post"
531
+ @sended="onSuccess"
532
+ @error="onError"
533
+ >
534
+ <AwInput
535
+ name="email"
536
+ label="Email"
537
+ type="email"
538
+ required
539
+ />
540
+
541
+ <AwPassword
542
+ name="password"
543
+ label="Password"
544
+ required
545
+ />
546
+
547
+ <AwButton type="submit" :loading="isLoading">
548
+ Sign In
549
+ </AwButton>
550
+ </AwForm>
551
+ </template>
552
+
553
+ <script>
554
+ export default {
555
+ data() {
556
+ return {
557
+ isLoading: false
558
+ }
559
+ },
560
+
561
+ methods: {
562
+ onSuccess(response) {
563
+ this.$router.push('/dashboard')
564
+ },
565
+
566
+ onError(error) {
567
+ console.error('Login failed:', error)
568
+ }
569
+ }
570
+ }
571
+ </script>
572
+ ```
573
+
574
+ ### Registration Form
575
+
576
+ ```markup
577
+ <template>
578
+ <AwForm url="/api/register" method="post" @sended="onRegistered">
579
+ <AwInput name="name" label="Full Name" required />
580
+
581
+ <AwInput name="email" label="Email" type="email" required />
582
+
583
+ <AwPassword name="password" label="Password" required />
584
+
585
+ <AwPassword name="password_confirmation" label="Confirm Password" required />
586
+
587
+ <AwCheckbox name="terms" required>
588
+ I agree to the Terms of Service
589
+ </AwCheckbox>
590
+
591
+ <AwButton type="submit" size="lg">
592
+ Create Account
593
+ </AwButton>
594
+ </AwForm>
595
+ </template>
596
+ ```
597
+
598
+ ## Form Inputs
599
+
600
+ ### Text Inputs
601
+
602
+ ```markup
603
+ <AwForm url="/api/profile" method="patch">
604
+ <!-- Basic text input -->
605
+ <AwInput name="first_name" label="First Name" />
606
+
607
+ <!-- With placeholder -->
608
+ <AwInput
609
+ name="company"
610
+ label="Company"
611
+ placeholder="Acme Inc."
612
+ />
613
+
614
+ <!-- With description -->
615
+ <AwDescriptionInput
616
+ name="username"
617
+ label="Username"
618
+ description="This will be your public identifier"
619
+ />
620
+
621
+ <!-- Textarea for long text -->
622
+ <AwTextarea
623
+ name="bio"
624
+ label="Biography"
625
+ rows="4"
626
+ />
627
+ </AwForm>
628
+ ```
629
+
630
+ ### Select & Dropdowns
631
+
632
+ ```markup
633
+ <AwForm url="/api/preferences" method="post">
634
+ <!-- Simple select -->
635
+ <AwSelect
636
+ name="country"
637
+ label="Country"
638
+ :options="['USA', 'Canada', 'UK', 'Germany']"
639
+ />
640
+
641
+ <!-- Select with objects -->
642
+ <AwSelectObject
643
+ name="timezone"
644
+ label="Timezone"
645
+ :options="timezones"
646
+ option-value="id"
647
+ option-label="name"
648
+ />
649
+
650
+ <!-- Native select (for better mobile UX) -->
651
+ <AwSelectNative
652
+ name="language"
653
+ label="Language"
654
+ :options="[
655
+ { value: 'en', text: 'English' },
656
+ { value: 'es', text: 'Spanish' },
657
+ { value: 'fr', text: 'French' }
658
+ ]"
659
+ />
660
+ </AwForm>
661
+ ```
662
+
663
+ ### Date & Time Inputs
664
+
665
+ ```markup
666
+ <AwForm url="/api/events" method="post">
667
+ <!-- Date picker -->
668
+ <AwDate
669
+ name="event_date"
670
+ label="Event Date"
671
+ :min="new Date()"
672
+ />
673
+
674
+ <!-- Birthday picker -->
675
+ <AwBirthdayPicker
676
+ name="birthday"
677
+ label="Date of Birth"
678
+ />
679
+
680
+ <!-- Calendar view -->
681
+ <AwCalendar
682
+ v-model="selectedDate"
683
+ name="appointment"
684
+ />
685
+ </AwForm>
686
+ ```
687
+
688
+ ### Checkboxes & Radios
689
+
690
+ ```markup
691
+ <AwForm url="/api/settings" method="patch">
692
+ <!-- Single checkbox -->
693
+ <AwCheckbox name="notifications">
694
+ Enable email notifications
695
+ </AwCheckbox>
696
+
697
+ <!-- Radio buttons -->
698
+ <div>
699
+ <label>Subscription Plan</label>
700
+ <AwRadio name="plan" value="free">Free</AwRadio>
701
+ <AwRadio name="plan" value="pro">Pro</AwRadio>
702
+ <AwRadio name="plan" value="enterprise">Enterprise</AwRadio>
703
+ </div>
704
+
705
+ <!-- Toggle switcher -->
706
+ <AwSwitcher name="dark_mode" label="Dark Mode" />
707
+ </AwForm>
708
+ ```
709
+
710
+ ### Specialized Inputs
711
+
712
+ ```markup
713
+ <AwForm url="/api/profile" method="patch">
714
+ <!-- Telephone input -->
715
+ <AwTel name="phone" label="Phone Number" />
716
+
717
+ <!-- Money input -->
718
+ <AwMoney name="budget" label="Budget" currency="USD" />
719
+
720
+ <!-- Code input -->
721
+ <AwCode name="verification_code" label="Verification Code" />
722
+
723
+ <!-- Slider -->
724
+ <AwSlider name="volume" label="Volume" :min="0" :max="100" />
725
+
726
+ <!-- Chip select -->
727
+ <AwChipSelect
728
+ name="skills"
729
+ label="Skills"
730
+ :options="['Vue.js', 'React', 'Angular', 'Node.js']"
731
+ />
732
+ </AwForm>
733
+ ```
734
+
735
+ ## Validation & Errors
736
+
737
+ ### HTML5 Validation
738
+
739
+ ```markup
740
+ <AwForm url="/api/submit" method="post">
741
+ <!-- Required field -->
742
+ <AwInput name="email" label="Email" required />
743
+
744
+ <!-- Email validation -->
745
+ <AwInput name="email" label="Email" type="email" required />
746
+
747
+ <!-- Pattern validation -->
748
+ <AwInput
749
+ name="username"
750
+ label="Username"
751
+ pattern="[a-zA-Z0-9_]+"
752
+ title="Only letters, numbers, and underscores"
753
+ />
754
+
755
+ <!-- Min/max length -->
756
+ <AwInput
757
+ name="password"
758
+ label="Password"
759
+ type="password"
760
+ minlength="8"
761
+ maxlength="100"
762
+ />
763
+ </AwForm>
764
+ ```
765
+
766
+ ### Server-Side Error Handling
767
+
768
+ ```markup
769
+ <template>
770
+ <AwForm
771
+ ref="form"
772
+ url="/api/users"
773
+ method="post"
774
+ @error="handleErrors"
775
+ >
776
+ <AwInput name="email" label="Email" />
777
+ <AwInput name="username" label="Username" />
778
+ <AwButton type="submit">Submit</AwButton>
779
+ </AwForm>
780
+ </template>
781
+
782
+ <script>
783
+ export default {
784
+ methods: {
785
+ handleErrors(error) {
786
+ // AwForm automatically sets field errors via setCustomValidity
787
+ // The errors are displayed on the respective input fields
788
+
789
+ // Optionally handle specific error codes
790
+ if (error.response?.status === 422) {
791
+ console.log('Validation failed:', error.response.data.errors)
792
+ }
793
+ },
794
+
795
+ // Programmatically set errors
796
+ setCustomErrors() {
797
+ this.$refs.form.setErrors({
798
+ email: 'Email is already taken',
799
+ username: 'Username must be unique'
800
+ })
801
+ },
802
+
803
+ // Clear all errors
804
+ clearErrors() {
805
+ this.$refs.form.resetErrors()
806
+ }
807
+ }
808
+ }
809
+ </script>
810
+ ```
811
+
812
+ ### Custom Validation
813
+
814
+ ```markup
815
+ <template>
816
+ <AwForm url="/api/submit" @submit.prevent="validateAndSubmit">
817
+ <AwInput
818
+ ref="password"
819
+ v-model="password"
820
+ name="password"
821
+ label="Password"
822
+ type="password"
823
+ />
824
+
825
+ <AwInput
826
+ ref="passwordConfirm"
827
+ v-model="passwordConfirm"
828
+ name="password_confirmation"
829
+ label="Confirm Password"
830
+ type="password"
831
+ />
832
+
833
+ <AwButton type="submit">Submit</AwButton>
834
+ </AwForm>
835
+ </template>
836
+
837
+ <script>
838
+ export default {
839
+ data() {
840
+ return {
841
+ password: '',
842
+ passwordConfirm: ''
843
+ }
844
+ },
845
+
846
+ methods: {
847
+ validateAndSubmit(event) {
848
+ // Clear previous errors
849
+ this.$refs.password.$el.querySelector('input').setCustomValidity('')
850
+ this.$refs.passwordConfirm.$el.querySelector('input').setCustomValidity('')
851
+
852
+ // Custom validation
853
+ if (this.password !== this.passwordConfirm) {
854
+ this.$refs.passwordConfirm.$el
855
+ .querySelector('input')
856
+ .setCustomValidity('Passwords do not match')
857
+ return
858
+ }
859
+
860
+ // Submit if valid
861
+ event.target.submit()
862
+ }
863
+ }
864
+ }
865
+ </script>
866
+ ```
867
+
868
+ ## File Uploads
869
+
870
+ ### Single File Upload
871
+
872
+ ```markup
873
+ <AwForm url="/api/avatar" method="post" enctype="multipart/form-data">
874
+ <AwUploader
875
+ name="avatar"
876
+ label="Profile Picture"
877
+ accept="image/*"
878
+ :max-size="5242880"
879
+ />
880
+
881
+ <AwButton type="submit">Upload</AwButton>
882
+ </AwForm>
883
+ ```
884
+
885
+ ### Multiple Files Upload
886
+
887
+ ```markup
888
+ <AwForm url="/api/documents" method="post">
889
+ <AwUploaderFiles
890
+ name="documents"
891
+ label="Documents"
892
+ multiple
893
+ :max-files="5"
894
+ accept=".pdf,.doc,.docx"
895
+ />
896
+
897
+ <AwButton type="submit">Upload Documents</AwButton>
898
+ </AwForm>
899
+ ```
900
+
901
+ ### Image Upload with Cropper
902
+
903
+ ```markup
904
+ <template>
905
+ <AwForm url="/api/profile-image" method="post">
906
+ <AwCropper
907
+ v-model="croppedImage"
908
+ name="profile_image"
909
+ label="Profile Image"
910
+ :aspect-ratio="1"
911
+ :max-size="2097152"
912
+ />
913
+
914
+ <AwButton type="submit" :disabled="!croppedImage">
915
+ Save Image
916
+ </AwButton>
917
+ </AwForm>
918
+ </template>
919
+ ```
920
+
921
+ ## Complex Forms
922
+
923
+ ### Form with Nested Data
924
+
925
+ ```markup
926
+ <template>
927
+ <AwForm url="/api/companies" method="post" @sended="onSuccess">
928
+ <!-- Company details -->
929
+ <AwInput name="company[name]" label="Company Name" />
930
+ <AwInput name="company[tax_id]" label="Tax ID" />
931
+
932
+ <!-- Address -->
933
+ <AwAddress
934
+ name="company[address]"
935
+ label="Company Address"
936
+ :with-google-maps="true"
937
+ />
938
+
939
+ <!-- Contact person -->
940
+ <AwInput name="contact[name]" label="Contact Name" />
941
+ <AwInput name="contact[email]" label="Contact Email" type="email" />
942
+ <AwTel name="contact[phone]" label="Contact Phone" />
943
+
944
+ <AwButton type="submit">Create Company</AwButton>
945
+ </AwForm>
946
+ </template>
947
+ ```
948
+
949
+ ### Dynamic Form Fields
950
+
951
+ ```markup
952
+ <template>
953
+ <AwForm url="/api/projects" method="post">
954
+ <AwInput name="project_name" label="Project Name" />
955
+
956
+ <!-- Dynamic team members -->
957
+ <div v-for="(member, index) in members" :key="index">
958
+ <h4>Team Member {{ index + 1 }}</h4>
959
+ <AwInput :name="`members[${index}][name]`" label="Name" />
960
+ <AwInput :name="`members[${index}][email]`" label="Email" type="email" />
961
+ <AwButton @click="removeMember(index)" theme="outline" color="error">
962
+ Remove
963
+ </AwButton>
964
+ </div>
965
+
966
+ <AwButton @click="addMember" theme="outline">
967
+ Add Team Member
968
+ </AwButton>
969
+
970
+ <AwButton type="submit">Create Project</AwButton>
971
+ </AwForm>
972
+ </template>
973
+
974
+ <script>
975
+ export default {
976
+ data() {
977
+ return {
978
+ members: [{ name: '', email: '' }]
979
+ }
980
+ },
981
+
982
+ methods: {
983
+ addMember() {
984
+ this.members.push({ name: '', email: '' })
985
+ },
986
+
987
+ removeMember(index) {
988
+ this.members.splice(index, 1)
989
+ }
990
+ }
991
+ }
992
+ </script>
993
+ ```
994
+
995
+ ## Modal Forms
996
+
997
+ ### Simple Modal Form
998
+
999
+ ```markup
1000
+ <template>
1001
+ <AwModal :show="showModal" @close="showModal = false">
1002
+ <template #title>Create New User</template>
1003
+
1004
+ <AwForm url="/api/users" method="post" @sended="onUserCreated">
1005
+ <AwInput name="name" label="Name" required />
1006
+ <AwInput name="email" label="Email" type="email" required />
1007
+ <AwSelect name="role" label="Role" :options="roles" />
1008
+
1009
+ <template #buttons>
1010
+ <AwButton type="submit">Create User</AwButton>
1011
+ <AwButton @click="showModal = false" color="mono">
1012
+ Cancel
1013
+ </AwButton>
1014
+ </template>
1015
+ </AwForm>
1016
+ </AwModal>
1017
+ </template>
1018
+
1019
+ <script>
1020
+ export default {
1021
+ data() {
1022
+ return {
1023
+ showModal: false,
1024
+ roles: ['Admin', 'Editor', 'Viewer']
1025
+ }
1026
+ },
1027
+
1028
+ methods: {
1029
+ onUserCreated(response) {
1030
+ this.showModal = false
1031
+ this.$notify({ title: 'User created successfully!' })
1032
+ }
1033
+ }
1034
+ }
1035
+ </script>
1036
+ ```
1037
+
1038
+ ## Multi-Step Forms
1039
+
1040
+ ### Multi-Step Registration
1041
+
1042
+ ```markup
1043
+ <template>
1044
+ <div>
1045
+ <AwProgress :value="(currentStep / totalSteps) * 100" />
1046
+
1047
+ <AwForm
1048
+ ref="form"
1049
+ url="/api/register"
1050
+ method="post"
1051
+ @submit.prevent="handleStep"
1052
+ >
1053
+ <!-- Step 1: Basic Info -->
1054
+ <div v-show="currentStep === 1">
1055
+ <h2>Step 1: Basic Information</h2>
1056
+ <AwInput v-model="formData.name" name="name" label="Full Name" required />
1057
+ <AwInput v-model="formData.email" name="email" label="Email" type="email" required />
1058
+ <AwPassword v-model="formData.password" name="password" label="Password" required />
1059
+ </div>
1060
+
1061
+ <!-- Step 2: Profile -->
1062
+ <div v-show="currentStep === 2">
1063
+ <h2>Step 2: Profile Details</h2>
1064
+ <AwBirthdayPicker v-model="formData.birthday" name="birthday" label="Birthday" />
1065
+ <AwTel v-model="formData.phone" name="phone" label="Phone" />
1066
+ <AwTextarea v-model="formData.bio" name="bio" label="Bio" />
1067
+ </div>
1068
+
1069
+ <!-- Step 3: Preferences -->
1070
+ <div v-show="currentStep === 3">
1071
+ <h2>Step 3: Preferences</h2>
1072
+ <AwSelect v-model="formData.timezone" name="timezone" label="Timezone" :options="timezones" />
1073
+ <AwCheckbox v-model="formData.newsletter" name="newsletter">
1074
+ Subscribe to newsletter
1075
+ </AwCheckbox>
1076
+ </div>
1077
+
1078
+ <!-- Navigation -->
1079
+ <AwFlow justify="between">
1080
+ <AwButton
1081
+ v-if="currentStep > 1"
1082
+ @click="currentStep--"
1083
+ theme="outline"
1084
+ >
1085
+ Previous
1086
+ </AwButton>
1087
+
1088
+ <AwButton v-if="currentStep < totalSteps" type="button" @click="nextStep">
1089
+ Next
1090
+ </AwButton>
1091
+
1092
+ <AwButton v-else type="submit">
1093
+ Complete Registration
1094
+ </AwButton>
1095
+ </AwFlow>
1096
+ </AwForm>
1097
+ </div>
1098
+ </template>
1099
+
1100
+ <script>
1101
+ export default {
1102
+ data() {
1103
+ return {
1104
+ currentStep: 1,
1105
+ totalSteps: 3,
1106
+ formData: {
1107
+ name: '',
1108
+ email: '',
1109
+ password: '',
1110
+ birthday: null,
1111
+ phone: '',
1112
+ bio: '',
1113
+ timezone: '',
1114
+ newsletter: false
1115
+ },
1116
+ timezones: ['UTC', 'EST', 'PST', 'GMT']
1117
+ }
1118
+ },
1119
+
1120
+ methods: {
1121
+ nextStep() {
1122
+ // Validate current step before proceeding
1123
+ if (this.$refs.form.$el.checkValidity()) {
1124
+ this.currentStep++
1125
+ } else {
1126
+ this.$refs.form.$el.reportValidity()
1127
+ }
1128
+ },
1129
+
1130
+ handleStep(event) {
1131
+ // Final submission
1132
+ event.target.submit()
1133
+ }
1134
+ }
1135
+ }
1136
+ </script>
1137
+ ```
1138
+
1139
+ ## Best Practices
1140
+
1141
+ ### 1. Choose the Right Form Component
1142
+
1143
+ ```markup
1144
+ <!-- Good: Use AwModelEdit for CRUD operations -->
1145
+ <AwModelEdit :model="user">
1146
+ <AwInput v-model="user.email" :error="user.errors.email" label="Email" />
1147
+ </AwModelEdit>
1148
+
1149
+ <!-- Good: Use AwForm for one-off operations -->
1150
+ <AwForm url="/api/login" method="post">
1151
+ <AwInput name="email" label="Email" />
1152
+ <AwButton type="submit">Login</AwButton>
1153
+ </AwForm>
1154
+
1155
+ <!-- Bad: Using AwForm for editing records (no change detection) -->
1156
+ <AwForm url="/api/users/1" method="patch">
1157
+ <AwInput name="email" label="Email" />
1158
+ </AwForm>
1159
+ ```
1160
+
1161
+ ### 2. Always Use Labels
1162
+
1163
+ ```markup
1164
+ <!-- Good -->
1165
+ <AwInput name="email" label="Email" />
1166
+
1167
+ <!-- Bad -->
1168
+ <AwInput name="email" placeholder="Email" />
1169
+ ```
1170
+
1171
+ ### 3. Provide Clear Feedback
1172
+
1173
+ ```markup
1174
+ <AwForm url="/api/save" @sended="onSuccess" @error="onError">
1175
+ <AwInput name="title" label="Title" />
1176
+ <AwButton type="submit" :loading="isSubmitting">
1177
+ {{ isSubmitting ? 'Saving...' : 'Save' }}
1178
+ </AwButton>
1179
+ </AwForm>
1180
+ ```
1181
+
1182
+ ### 4. Handle Loading States
1183
+
1184
+ For form data loading, use `AwContentPlaceholder`:
1185
+
1186
+ ```markup
1187
+ <template>
1188
+ <AwContentPlaceholder v-if="loading" type="form" :lines="4" />
1189
+
1190
+ <AwForm v-else ref="form" url="/api/submit" @submit="onSubmit">
1191
+ <AwInput name="data" label="Data" />
1192
+ <AwButton type="submit">Submit</AwButton>
1193
+ </AwForm>
1194
+ </template>
1195
+
1196
+ <script>
1197
+ export default {
1198
+ data() {
1199
+ return {
1200
+ loading: true
1201
+ }
1202
+ },
1203
+ async mounted() {
1204
+ await this.loadFormData()
1205
+ this.loading = false
1206
+ }
1207
+ }
1208
+ </script>
1209
+ ```
1210
+
1211
+ For complex forms with multiple sections:
1212
+
1213
+ ```markup
1214
+ <template>
1215
+ <AwGrid v-if="loading" :col="{ lg: 3 }">
1216
+ <div span="{ lg: 2 }">
1217
+ <AwContentPlaceholder type="form" :lines="8" />
1218
+ </div>
1219
+ <div>
1220
+ <AwContentPlaceholder type="form" :lines="4" />
1221
+ </div>
1222
+ </AwGrid>
1223
+
1224
+ <AwForm v-else url="/api/submit">
1225
+ <!-- Form content -->
1226
+ </AwForm>
1227
+ </template>
1228
+ ```
1229
+
1230
+ ### 5. Use Appropriate Input Types
1231
+
1232
+ ```markup
1233
+ <!-- Email validation -->
1234
+ <AwInput name="email" label="Email" type="email" />
1235
+
1236
+ <!-- Number input -->
1237
+ <AwInput name="age" label="Age" type="number" :min="0" :max="120" />
1238
+
1239
+ <!-- URL input -->
1240
+ <AwInput name="website" label="Website" type="url" />
1241
+ ```
1242
+
1243
+ ### 6. Group Related Fields
1244
+
1245
+ ```markup
1246
+ <AwForm url="/api/users" method="post">
1247
+ <AwCard title="Personal Information">
1248
+ <AwInput name="first_name" label="First Name" />
1249
+ <AwInput name="last_name" label="Last Name" />
1250
+ <AwBirthdayPicker name="birthday" label="Birthday" />
1251
+ </AwCard>
1252
+
1253
+ <AwCard title="Contact Information">
1254
+ <AwInput name="email" label="Email" type="email" />
1255
+ <AwTel name="phone" label="Phone" />
1256
+ </AwCard>
1257
+
1258
+ <AwButton type="submit">Save</AwButton>
1259
+ </AwForm>
1260
+ ```
1261
+
1262
+ ### 7. Provide Help Text
1263
+
1264
+ ```markup
1265
+ <AwDescriptionInput
1266
+ name="api_key"
1267
+ label="API Key"
1268
+ description="You can find your API key in the developer settings"
1269
+ type="password"
1270
+ />
1271
+ ```
1272
+
1273
+ ### 8. Use Method Override for PUT/PATCH
1274
+
1275
+ ```markup
1276
+ <!-- For Laravel/REST APIs that don't support PUT/PATCH natively -->
1277
+ <AwForm url="/api/users/1" method="patch">
1278
+ <AwInput name="name" label="Name" />
1279
+ <AwButton type="submit">Update</AwButton>
1280
+ </AwForm>
1281
+ ```
1282
+
1283
+ ## Common Patterns
1284
+
1285
+ ### Search Form
1286
+
1287
+ ```markup
1288
+ <AwForm url="/api/search" method="get">
1289
+ <AwSearch
1290
+ name="q"
1291
+ placeholder="Search..."
1292
+ @input="debounceSearch"
1293
+ />
1294
+ </AwForm>
1295
+ ```
1296
+
1297
+ ### Filter Form
1298
+
1299
+ ```markup
1300
+ <AwForm url="/api/products" method="get">
1301
+ <AwSelect name="category" label="Category" :options="categories" />
1302
+ <AwSlider name="price_min" label="Min Price" :min="0" :max="1000" />
1303
+ <AwSlider name="price_max" label="Max Price" :min="0" :max="1000" />
1304
+ <AwButton type="submit">Apply Filters</AwButton>
1305
+ <AwButton type="reset" theme="outline">Reset</AwButton>
1306
+ </AwForm>
1307
+ ```
1308
+
1309
+ ### Inline Edit Form
1310
+
1311
+ ```markup
1312
+ <AwForm url="/api/tasks/1" method="patch" @sended="onSaved">
1313
+ <AwInput
1314
+ v-model="taskName"
1315
+ name="name"
1316
+ @blur="$refs.form.$el.submit()"
1317
+ />
1318
+ </AwForm>
1319
+ ```
1320
+
1321
+ ---
1322
+
1323
+ For more examples, see individual component documentation:
1324
+ - [AwModelEdit](../components/organisms/aw-model-edit.md) - Model-based forms (recommended)
1325
+ - [AwForm](../components/organisms/aw-form.md) - Raw form submission
1326
+ - [AwInput](../components/atoms/aw-input.md) - Text inputs
1327
+ - [AwSelect](../components/molecules/aw-select.md) - Select dropdowns
1328
+ - [AwUploader](../components/organisms/aw-uploader.md) - File uploads
1329
+ - [Vue-MC Models Guide](../../vue-mc/docs/models.md) - Model definitions