viewlogic 1.2.1 → 1.2.2

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
@@ -338,10 +338,15 @@ const current = router.getCurrentRoute();
338
338
  // In route components - global methods automatically available:
339
339
  export default {
340
340
  dataURL: '/api/products', // Auto-fetch data
341
- mounted() {
341
+ async mounted() {
342
342
  const id = this.getParam('id'); // Get parameter
343
343
  this.navigateTo('detail', { id }); // Navigate
344
344
  console.log('Data loaded:', this.products); // From dataURL
345
+
346
+ // New $api pattern for RESTful API calls
347
+ const user = await this.$api.get('/api/users/{userId}');
348
+ await this.$api.post('/api/analytics', { pageView: 'products' });
349
+
345
350
  if (this.$isAuthenticated()) { /* auth check */ }
346
351
  const text = this.$t('welcome.message'); // i18n
347
352
  }
@@ -351,9 +356,9 @@ export default {
351
356
  ### Key Global Methods (Auto-available in all route components)
352
357
  - **Navigation**: `navigateTo()`, `getCurrentRoute()`
353
358
  - **Parameters**: `getParams()`, `getParam(key, defaultValue)`
354
- - **Data Fetching**: `$fetchData()`, `$fetchAllData()` (with dataURL)
359
+ - **Data Fetching**: `$fetchData()` (with dataURL), `$api.get()`, `$api.post()`, `$api.put()`, `$api.patch()`, `$api.delete()`
355
360
  - **Authentication**: `$isAuthenticated()`, `$getToken()`, `$logout()`
356
- - **Forms**: Auto-binding with `action` attribute and `{param}` templates
361
+ - **Forms**: Auto-binding with `action` attribute, duplicate prevention, validation
357
362
  - **i18n**: `$t(key, params)` for translations
358
363
 
359
364
  ### Auto-Injected Properties
@@ -659,9 +664,98 @@ export default {
659
664
  - ✅ **Built-in Security** - HTML sanitization included
660
665
  - ✅ **Zero Setup** - Works immediately without configuration
661
666
 
662
- ## 📝 Automatic Form Handling with Variable Parameters
667
+ ## 🔥 RESTful API Calls with $api Pattern
668
+
669
+ ViewLogic introduces a clean, RESTful API calling pattern with automatic parameter substitution and authentication handling.
670
+
671
+ ### Basic API Usage
672
+
673
+ ```javascript
674
+ // src/logic/user-profile.js
675
+ export default {
676
+ name: 'UserProfile',
677
+
678
+ async mounted() {
679
+ try {
680
+ // GET request with automatic parameter substitution
681
+ const user = await this.$api.get('/api/users/{userId}');
682
+
683
+ // POST request with data
684
+ const response = await this.$api.post('/api/users/{userId}/posts', {
685
+ title: 'New Post',
686
+ content: 'Post content here'
687
+ });
688
+
689
+ // PUT request for updates
690
+ await this.$api.put('/api/users/{userId}', {
691
+ name: user.name,
692
+ email: user.email
693
+ });
694
+
695
+ // DELETE request
696
+ await this.$api.delete('/api/posts/{postId}');
697
+
698
+ } catch (error) {
699
+ console.error('API call failed:', error);
700
+ this.handleError(error);
701
+ }
702
+ }
703
+ };
704
+ ```
705
+
706
+ ### Advanced API Features
707
+
708
+ ```javascript
709
+ export default {
710
+ methods: {
711
+ async handleUserActions() {
712
+ // With custom headers
713
+ const data = await this.$api.get('/api/protected-data', {
714
+ headers: { 'X-Custom-Header': 'value' }
715
+ });
716
+
717
+ // File upload with FormData
718
+ const formData = new FormData();
719
+ formData.append('file', this.selectedFile);
720
+ await this.$api.post('/api/upload', formData);
721
+
722
+ // With query parameters (automatically added from current route)
723
+ // URL: /users?id=123 → API call includes ?id=123
724
+ const result = await this.$api.get('/api/user-data');
725
+ },
726
+
727
+ // Error handling patterns
728
+ async safeApiCall() {
729
+ try {
730
+ const user = await this.$api.get('/api/users/{userId}');
731
+ this.user = user;
732
+
733
+ } catch (error) {
734
+ if (error.message.includes('404')) {
735
+ this.showError('User not found');
736
+ } else if (error.message.includes('401')) {
737
+ this.navigateTo('login');
738
+ } else {
739
+ this.showError('Something went wrong');
740
+ }
741
+ }
742
+ }
743
+ }
744
+ };
745
+ ```
746
+
747
+ ### Key $api Features
663
748
 
664
- ViewLogic Router includes revolutionary automatic form handling that eliminates the need for manual form submission logic. Just define your forms with `action` attributes and the router handles the rest!
749
+ - **🎯 Parameter Substitution**: `{userId}` automatically replaced with component data or route params
750
+ - **🔐 Auto Authentication**: Authorization headers automatically added when token is available
751
+ - **📄 Smart Data Handling**: JSON and FormData automatically detected and processed
752
+ - **🔗 Query Integration**: Current route query parameters automatically included
753
+ - **⚡ Error Standardization**: Consistent error format across all API calls
754
+ - **🚀 RESTful Pattern**: Clean `get()`, `post()`, `put()`, `patch()`, `delete()` methods
755
+
756
+ ## 📝 Advanced Form Handling with Smart Features
757
+
758
+ ViewLogic Router includes revolutionary automatic form handling with duplicate prevention, validation, and error handling. Just define your forms with `action` attributes and the router handles everything!
665
759
 
666
760
  ### Basic Form Handling
667
761
 
@@ -683,14 +777,81 @@ ViewLogic Router includes revolutionary automatic form handling that eliminates
683
777
  export default {
684
778
  name: 'ContactPage',
685
779
  mounted() {
686
- // Forms are automatically bound - no additional code needed!
687
- // Form submission will automatically POST to /api/contact
688
- console.log('Form handling is automatic!');
780
+ // Forms are automatically bound with smart features:
781
+ // Duplicate submission prevention
782
+ // Automatic validation
783
+ // ✅ Loading state management
784
+ // ✅ Error handling
785
+ console.log('Smart form handling is automatic!');
689
786
  }
690
787
  };
691
788
  ```
692
789
 
693
- ### Variable Parameter Forms - 🆕 Revolutionary!
790
+ ### Smart Form Features - 🆕 Enhanced!
791
+
792
+ ViewLogic FormHandler now includes advanced features for production-ready applications:
793
+
794
+ ```html
795
+ <!-- Smart form with all features -->
796
+ <form action="/api/users/{userId}/update" method="PUT"
797
+ class="auto-form"
798
+ data-success-handler="handleSuccess"
799
+ data-error-handler="handleError"
800
+ data-loading-handler="handleLoading"
801
+ data-redirect="/profile">
802
+
803
+ <input type="text" name="name" required
804
+ data-validation="validateName">
805
+ <input type="email" name="email" required>
806
+ <button type="submit">Update Profile</button>
807
+ </form>
808
+ ```
809
+
810
+ ```javascript
811
+ export default {
812
+ methods: {
813
+ // Custom validation
814
+ validateName(value) {
815
+ return value.length >= 2 && value.length <= 50;
816
+ },
817
+
818
+ // Success handler
819
+ handleSuccess(response, form) {
820
+ this.showToast('Profile updated successfully!', 'success');
821
+ // Automatic redirect to /profile happens after this
822
+ },
823
+
824
+ // Error handler with smart error detection
825
+ handleError(error, form) {
826
+ if (error.message.includes('validation')) {
827
+ this.showToast('Please check your input', 'warning');
828
+ } else {
829
+ this.showToast('Update failed. Please try again.', 'error');
830
+ }
831
+ },
832
+
833
+ // Loading state handler
834
+ handleLoading(isLoading, form) {
835
+ const button = form.querySelector('button[type="submit"]');
836
+ button.disabled = isLoading;
837
+ button.textContent = isLoading ? 'Updating...' : 'Update Profile';
838
+ }
839
+ }
840
+ };
841
+ ```
842
+
843
+ ### Key Form Features
844
+
845
+ - **🚫 Duplicate Prevention**: Automatic duplicate submission blocking
846
+ - **⏱️ Timeout Management**: 30-second default timeout with abort capability
847
+ - **✅ Built-in Validation**: HTML5 + custom validation functions
848
+ - **🔄 Loading States**: Automatic loading state management
849
+ - **🎯 Smart Error Handling**: Network vs validation error distinction
850
+ - **📄 File Upload Support**: Automatic FormData vs JSON detection
851
+ - **🔀 Auto Redirect**: Post-success navigation
852
+ - **🏷️ Parameter Substitution**: Dynamic URL parameter replacement
853
+
854
+ ### Variable Parameter Forms - Revolutionary!
694
855
 
695
856
  The most powerful feature is **variable parameter support** in action URLs. You can use simple template syntax to inject dynamic values:
696
857
 
@@ -1885,6 +1885,20 @@ var ApiHandler = class {
1885
1885
  async delete(url, component = null, options = {}) {
1886
1886
  return this.fetchData(url, component, { ...options, method: "DELETE" });
1887
1887
  }
1888
+ /**
1889
+ * 컴포넌트에 바인딩된 API 객체 생성
1890
+ */
1891
+ bindToComponent(component) {
1892
+ return {
1893
+ get: (url, options = {}) => this.get(url, component, options),
1894
+ post: (url, data, options = {}) => this.post(url, data, component, options),
1895
+ put: (url, data, options = {}) => this.put(url, data, component, options),
1896
+ patch: (url, data, options = {}) => this.patch(url, data, component, options),
1897
+ delete: (url, options = {}) => this.delete(url, component, options),
1898
+ fetchData: (url, options = {}) => this.fetchData(url, component, options),
1899
+ fetchMultipleData: (dataConfig) => this.fetchMultipleData(dataConfig, component)
1900
+ };
1901
+ }
1888
1902
  /**
1889
1903
  * 정리 (메모리 누수 방지)
1890
1904
  */
@@ -2359,6 +2373,7 @@ ${template}`;
2359
2373
  }
2360
2374
  },
2361
2375
  async mounted() {
2376
+ this.$api = router.routeLoader.apiHandler.bindToComponent(this);
2362
2377
  if (script.mounted) {
2363
2378
  await script.mounted.call(this);
2364
2379
  }
@@ -2425,22 +2440,6 @@ ${template}`;
2425
2440
  } finally {
2426
2441
  this.$dataLoading = false;
2427
2442
  }
2428
- },
2429
- // HTTP 메서드 래퍼들 (ApiHandler 직접 접근)
2430
- async $get(url, options = {}) {
2431
- return await router.routeLoader.apiHandler.get(url, this, options);
2432
- },
2433
- async $post(url, data, options = {}) {
2434
- return await router.routeLoader.apiHandler.post(url, data, this, options);
2435
- },
2436
- async $put(url, data, options = {}) {
2437
- return await router.routeLoader.apiHandler.put(url, data, this, options);
2438
- },
2439
- async $patch(url, data, options = {}) {
2440
- return await router.routeLoader.apiHandler.patch(url, data, this, options);
2441
- },
2442
- async $delete(url, options = {}) {
2443
- return await router.routeLoader.apiHandler.delete(url, this, options);
2444
2443
  }
2445
2444
  },
2446
2445
  _routeName: routeName