Appearance
@xcomputed Decorator
The @xcomputed decorator is used to create computed properties in widgets. These properties, defined with getter methods, are automatically recalculated when their dependent values change, and their results are cached.
Basic Usage
Syntax
Manual Dependency Declaration
typescript
@xcomputed({ dependencies: ['property1', 'property2'] })
get computedValue(): returnType {
return computation;
}Automatic Dependency Detection
typescript
@xcomputed({ autoDetectDependencies: true })
get computedValue(): returnType {
// Used properties are automatically detected
return computation;
}Examples
Form Validation
Shopping Cart
Nested Dependencies
Performance Optimization
Cache Mechanism
typescript
export class OptimizedWidget {
@xproperty()
largeData: number[] = [];
// Expensive calculation - only runs when largeData changes
@xcomputed({ dependencies: ['largeData'] })
get expensiveCalculation(): number {
console.log('Calculating...'); // Only when necessary
return this.largeData.reduce((sum, num, i) => {
return sum + (num * Math.pow(i + 1, 2));
}, 0);
}
// Cached result
@xcomputed({ dependencies: ['expensiveCalculation'] })
get formattedResult(): string {
return `Result: ${this.expensiveCalculation.toLocaleString()}`;
}
}Manual Cache Invalidation
typescript
import { invalidateComputed, invalidateAllComputed } from '@xcons/widget';
export class ManualInvalidationWidget {
@xproperty()
data: string = '';
@xcomputed({ dependencies: ['data'] })
get processedData(): string {
return this.data.toUpperCase();
}
// Clear a single computed property
clearCache(): void {
invalidateComputed(this, 'processedData');
}
// Clear all computed properties
clearAllCaches(): void {
invalidateAllComputed(this);
}
}Error Handling
typescript
export class SafeComputedWidget {
@xproperty()
data: any = null;
@xcomputed({ dependencies: ['data'] })
get safeValue(): string {
try {
if (!this.data) return 'No data';
return this.data.value.toString();
} catch (error) {
console.error('Computed error:', error);
return 'Error occurred';
}
}
@xcomputed({ dependencies: ['data'] })
get fallbackValue(): string {
return this.data?.value?.toString() ?? 'Default value';
}
}Tips
✅ Correct Usage
typescript
// Explicitly declare dependencies
@xcomputed({ dependencies: ['prop1', 'prop2'] })
get result(): string {
return `${this.prop1} - ${this.prop2}`;
}
// Use computed for complex calculations
@xcomputed({ dependencies: ['items'] })
get totalPrice(): number {
return this.items.reduce((sum, item) => sum + item.price, 0);
}
// Chained computed properties
@xcomputed({ dependencies: ['firstName', 'lastName'] })
get fullName(): string {
return `${this.firstName} ${this.lastName}`;
}
@xcomputed({ dependencies: ['fullName'] })
get greeting(): string {
return `Hello, ${this.fullName}!`;
}❌ Incorrect Usage
typescript
// Creating side effects
@xcomputed({ dependencies: ['count'] })
get doubleCount(): number {
this.lastCalculated = Date.now(); // ❌ Side effect
return this.count * 2;
}
// Asynchronous operations
@xcomputed({ dependencies: ['id'] })
get user(): Promise<User> { // ❌ Async computed not supported
return fetch(`/api/users/${this.id}`);
}
// Using with setter
@xcomputed({ dependencies: ['value'] })
get computed(): number {
return this.value * 2;
}
set computed(val: number) { // ❌ Computed should only be getter
this.value = val / 2;
}Summary
With the @xcomputed decorator:
- ✅ Create computed properties
- ✅ Automatic cache mechanism
- ✅ Dependency tracking
- ✅ Automatic or manual dependency detection
- ✅ Nested dependencies
- ✅ Performance optimization
- ✅ Manual cache invalidation
Computed properties help you create performant and reactive user interfaces by optimizing complex calculations in widgets.