Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 67 additions & 8 deletions angular/projects/lib/src/lib/base-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,86 @@
*/

/**
* Base interface that all widgets need to implement in order for GridstackItemComponent to correctly save/load/delete/..
* Abstract base class that all custom widgets should extend.
*
* This class provides the interface needed for GridstackItemComponent to:
* - Serialize/deserialize widget data
* - Save/restore widget state
* - Integrate with Angular lifecycle
*
* Extend this class when creating custom widgets for dynamic grids.
*
* @example
* ```typescript
* @Component({
* selector: 'my-custom-widget',
* template: '<div>{{data}}</div>'
* })
* export class MyCustomWidget extends BaseWidget {
* @Input() data: string = '';
*
* serialize() {
* return { data: this.data };
* }
* }
* ```
*/

import { Injectable } from '@angular/core';
import { NgCompInputs, NgGridStackWidget } from './types';

@Injectable()
export abstract class BaseWidget {
/**
* Base widget class for GridStack Angular integration.
*/
@Injectable()
export abstract class BaseWidget {

/** variable that holds the complete definition of this widgets (with selector,x,y,w,h) */
/**
* Complete widget definition including position, size, and Angular-specific data.
* Populated automatically when the widget is loaded or saved.
*/
public widgetItem?: NgGridStackWidget;

/**
* REDEFINE to return an object representing the data needed to re-create yourself, other than `selector` already handled.
* This should map directly to the @Input() fields of this objects on create, so a simple apply can be used on read
* Override this method to return serializable data for this widget.
*
* Return an object with properties that map to your component's @Input() fields.
* The selector is handled automatically, so only include component-specific data.
*
* @returns Object containing serializable component data
*
* @example
* ```typescript
* serialize() {
* return {
* title: this.title,
* value: this.value,
* settings: this.settings
* };
* }
* ```
*/
public serialize(): NgCompInputs | undefined { return; }

/**
* REDEFINE this if your widget needs to read from saved data and transform it to create itself - you do this for
* things that are not mapped directly into @Input() fields for example.
* Override this method to handle widget restoration from saved data.
*
* Use this for complex initialization that goes beyond simple @Input() mapping.
* The default implementation automatically assigns input data to component properties.
*
* @param w The saved widget data including input properties
*
* @example
* ```typescript
* deserialize(w: NgGridStackWidget) {
* super.deserialize(w); // Call parent for basic setup
*
* // Custom initialization logic
* if (w.input?.complexData) {
* this.processComplexData(w.input.complexData);
* }
* }
* ```
*/
public deserialize(w: NgGridStackWidget) {
// save full description for meta data
Expand Down
54 changes: 48 additions & 6 deletions angular/projects/lib/src/lib/gridstack-item.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,34 @@ import { Component, ElementRef, Input, ViewChild, ViewContainerRef, OnDestroy, C
import { GridItemHTMLElement, GridStackNode } from 'gridstack';
import { BaseWidget } from './base-widget';

/** store element to Ng Class pointer back */
/**
* Extended HTMLElement interface for grid items.
* Stores a back-reference to the Angular component for integration.
*/
export interface GridItemCompHTMLElement extends GridItemHTMLElement {
/** Back-reference to the Angular GridStackItem component */
_gridItemComp?: GridstackItemComponent;
}

/**
* HTML Component Wrapper for gridstack items, in combination with GridstackComponent for parent grid
* Angular component wrapper for individual GridStack items.
*
* This component represents a single grid item and handles:
* - Dynamic content creation and management
* - Integration with parent GridStack component
* - Component lifecycle and cleanup
* - Widget options and configuration
*
* Use in combination with GridstackComponent for the parent grid.
*
* @example
* ```html
* <gridstack>
* <gridstack-item [options]="{x: 0, y: 0, w: 2, h: 1}">
* <my-widget-component></my-widget-component>
* </gridstack-item>
* </gridstack>
* ```
*/
@Component({
selector: 'gridstack-item',
Expand All @@ -34,16 +55,37 @@ export interface GridItemCompHTMLElement extends GridItemHTMLElement {
})
export class GridstackItemComponent implements OnDestroy {

/** container to append items dynamically */
/**
* Container for dynamic component creation within this grid item.
* Used to append child components programmatically.
*/
@ViewChild('container', { read: ViewContainerRef, static: true}) public container?: ViewContainerRef;

/** ComponentRef of ourself - used by dynamic object to correctly get removed */
/**
* Component reference for dynamic component removal.
* Used internally when this component is created dynamically.
*/
public ref: ComponentRef<GridstackItemComponent> | undefined;

/** child component so we can save/restore additional data to be saved along */
/**
* Reference to child widget component for serialization.
* Used to save/restore additional data along with grid position.
*/
public childWidget: BaseWidget | undefined;

/** list of options for creating/updating this item */
/**
* Grid item configuration options.
* Defines position, size, and behavior of this grid item.
*
* @example
* ```typescript
* itemOptions: GridStackNode = {
* x: 0, y: 0, w: 2, h: 1,
* noResize: true,
* content: 'Item content'
* };
* ```
*/
@Input() public set options(val: GridStackNode) {
const grid = this.el.gridstackNode?.grid;
if (grid) {
Expand Down
Loading