XCon Studio widget utilities with advanced template rendering, reactive binding system and registry pattern support
npm install @xcons/widget@Widget decorator for component registration
@xproperty and @xcomputed decorators with automatic dependency tracking
OnWidgetInit, OnWidgetDestroy, etc.)
@xinject decorator
x:model directive
bash
npm install @xcons/widget
`
Quick Start
$3
`typescript
import { Widget, xproperty, xcomputed, OnWidgetInit } from '@xcons/widget';
@Widget({
selector: '.hello-widget',
widgetName: 'HelloWidget',
template:
Full Name:
Counter:
,
styles: [
]
})
export class HelloWidget implements OnWidgetInit {
@xproperty() name: string = 'World';
@xproperty() firstName: string = 'John';
@xproperty() lastName: string = 'Doe';
@xproperty() count: number = 0;
@xcomputed({ dependencies: ['firstName', 'lastName'] })
get fullName(): string {
return ${this.firstName} ${this.lastName};
}
onWidgetInit(): void {
console.log('HelloWidget initialized!');
}
incrementCount(): void {
this.count++;
}
}
`
$3
`typescript
import { XConBootstrap } from '@xcons/widget';
import { HelloWidget } from './hello-widget';
// Bootstrap the application with widgets
XConBootstrap.run({
widgets: [
{ widget: HelloWidget, initMode: 'auto' }
]
});
`
$3
`html
`
Advanced Usage
$3
`typescript
import { xinjectable, xsingleton, xinject } from '@xcons/widget';
// Service definition
@xsingleton()
export class UserService {
@xproperty() users: User[] = [];
async loadUsers(): Promise {
// Load users from API
this.users = await fetch('/api/users').then(r => r.json());
}
getUsers(): User[] {
return this.users;
}
}
// Using service in widget
@Widget({
selector: '.user-list',
template:
})
export class UserListWidget implements OnWidgetInit, OnWidgetReady {
@xproperty() searchQuery: string = '';
@xproperty() selectedUserId: number | null = null;
@xinject(UserService)
private userService: UserService;
@xcomputed({ dependencies: ['userService.users'] })
get userCount(): number {
return this.userService.getUsers().length;
}
@xcomputed({ dependencies: ['userService.users', 'searchQuery'] })
get filteredUsers(): User[] {
if (!this.searchQuery) {
return this.userService.getUsers();
}
const query = this.searchQuery.toLowerCase();
return this.userService.getUsers().filter(user =>
user.name.toLowerCase().includes(query)
);
}
onWidgetInit(): void {
console.log('UserListWidget initialized');
}
async onWidgetReady(templateReady: boolean): Promise {
if (templateReady) {
await this.userService.loadUsers();
}
}
selectUser(userId: number): void {
this.selectedUserId = userId;
}
}
// Start the application
XConBootstrap.run({
widgets: [
{ widget: UserListWidget, initMode: 'auto' }
],
services: [
{ service: UserService }
]
});
`
$3
XCon Widget allows you to create SEO-friendly web applications with its search engine optimized structure:
`typescript
@Widget({
selector: '.product-widget',
template:
})
export class ProductWidget implements OnWidgetInit {
@xproperty() product: Product = {
name: 'Product Name',
description: 'Product description',
imageUrl: '/images/product.jpg',
price: '199.99'
};
onWidgetInit(): void {
// Load initial data for server-side rendering
this.loadProductData();
}
async loadProductData(): Promise {
// Render critical content first for SEO
const productId = this.getProductIdFromUrl();
this.product = await this.fetchProduct(productId);
}
}
`
SEO Advantages:
- ā
Static HTML content support - Search engines can read content directly
- ā
Semantic HTML structure - Use of meaningful HTML elements
- ā
Structured Data support - Rich snippets with Schema.org markups
- ā
Progressive Enhancement - Basic content can be displayed without JavaScript
- ā
Fast initial render - Widgets bind on top of existing HTML
Template Syntax
$3
`html
`
$3
ā ļø Security Warning: Be careful when using x:html, it can lead to XSS (Cross-Site Scripting) vulnerabilities with untrusted content. Only use with trusted or sanitized HTML content.
`html
`
Example Usage:
`typescript
@Widget({
selector: '.content-widget',
template:
})
export class ContentWidget {
@xproperty() articleContent: string = 'Title
Content text
';
// Example of creating safe HTML content
setSafeContent(userInput: string): void {
// Sanitize content first
this.articleContent = this.sanitizeHtml(userInput);
}
private sanitizeHtml(html: string): string {
// Use HTML sanitization library (e.g., DOMPurify)
// return DOMPurify.sanitize(html);
return html;
}
}
`
$3
#### Conditional Rendering (x:if)
`html
This content is visible
Counter is greater than zero
`
#### List Rendering (x:for)
`html
:
`
#### Switch Cases (x:switch)
`html
Loading...
Successful!
An error occurred
Unknown state
`
#### Event Binding (x:on:*)
`html
`
#### Attribute Binding (x:attr:*)
`html
`
#### Class Binding (x:class:*)
`html
Content
`
#### Two-Way Binding (x:model)
`html
`
#### Isolation (x:isolate)
Ensures child widgets maintain their own independent binding contexts:
`html
`
API Reference
$3
#### @Widget(config)
Widget class decorator:
`typescript
@Widget({
selector: string, // CSS selector (required)
widgetName?: string, // Widget name
template?: string, // Inline HTML template
templateUrl?: string, // External HTML file path
styles?: string[], // Inline CSS styles
styleUrls?: string[], // External CSS file paths
encapsulation?: EncapsulationMode, // Style encapsulation mode
initMode?: InitializationMode, // Initialization mode
logger?: IWidgetLoggerConfig // Logger configuration
})
`
#### @xproperty(config?)
Reactive property decorator:
`typescript
@xproperty({
autoUpdate?: boolean, // Auto update (default: true)
deepWatch?: boolean // Deep watching (default: false)
})
`
#### @xcomputed(config?)
Computed property decorator:
`typescript
@xcomputed({
dependencies?: string[], // Explicit dependencies
autoDetectDependencies?: boolean // Auto dependency detection (default: true)
})
`
#### @xinject(token)
Service injection decorator:
`typescript
@xinject(ServiceClass) // Inject by class
@xinject('ServiceToken') // Inject by token
`
#### @xinjectable(config?)
Service registration decorator:
`typescript
@xinjectable({
scope?: 'singleton' | 'transient', // Service scope (default: 'singleton')
providedIn?: 'root' // Auto registration in root
})
`
$3
`typescript
interface OnWidgetInit {
onWidgetInit(): void;
}
interface OnWidgetReady {
onWidgetReady(templateReady: boolean): void;
}
interface OnWidgetDestroy {
onWidgetDestroy(): void;
}
interface OnWidgetRendered {
onWidgetRendered(container: HTMLElement): void;
}
interface OnWidgetDataUpdated {
onWidgetDataUpdated(): void;
}
interface OnWidgetResize {
onWidgetResize(): void;
}
interface OnWidgetEditModeChanged {
onWidgetEditModeChanged(): void;
}
interface OnWidgetMobileModeChanged {
onWidgetMobileModeChanged(): void;
}
interface OnWidgetPropertyChanged {
onWidgetPropertyChanged(propertyKey?: string, oldValue?: any, newValue?: any): void;
}
interface OnWidgetInitializationError {
onWidgetInitializationError(error: any): void;
}
`
$3
`typescript
// Bootstrap configuration
interface BootstrapConfig {
rootWidget?: any; // Single root widget
widgets?: BootstrapWidget[]; // Widget list
services?: BootstrapService[]; // Services to register
providers?: BootstrapProvider[]; // Custom providers
}
// Start the application
XConBootstrap.run(config: BootstrapConfig): Promise
// Rescan DOM for new widgets
XConBootstrap.rescanDOM(): void
// Setup auto-scan for dynamic content
XConBootstrap.setupAutoScan(): void
// Get widget instance from DOM element
XConBootstrap.getWidgetInstance(element: HTMLElement): any
// Destroy widget on element
XConBootstrap.destroyWidget(element: HTMLElement): boolean
`
$3
The framework provides a global XConWidgets object for widget management:
`typescript
// Registry access
XConWidgets.registry // Widget registry instance
XConWidgets.domManager // DOM management instance
// Widget registration
XConWidgets.registerWidget(selector, widgetClass, config, initMode)
// Widget activation
XConWidgets.activateWidget(widgetClass, context)
// Registry queries
XConWidgets.isRegistered(selector) // Check if registered
XConWidgets.getWidgets() // Get all selectors
XConWidgets.getRegisteredWidgets() // Get all with details
XConWidgets.getWidgetBySelector(selector) // Get widget by selector
// DOM management
XConWidgets.scanDOM() // Scan DOM for widgets
XConWidgets.rescanDOM() // Rescan DOM
XConWidgets.setupAutoScan() // Setup auto-scan
`
Browser Support
- Chrome 60+
- Firefox 60+
- Safari 12+
- Edge 79+
Dependencies
$3
- @xcons/core ^2.0.1
- @xcons/common ^2.0.16
- typescript >=4.5.0`