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()`, `$
|
|
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
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
|
687
|
-
//
|
|
688
|
-
|
|
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
|
-
###
|
|
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
|
|
package/dist/viewlogic-router.js
CHANGED
|
@@ -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
|