npm package: @ibsheet/angular
Description: An Angular wrapper component for IBSheet, providing seamless integration of IBSheet spreadsheet functionality into Angular applications.
Author: IB Leaders
Latest version: 1.1.0

# ibsheet-angular

An Angular wrapper component for IBSheet, providing seamless integration of IBSheet spreadsheet functionality into Angular applications.

## Features

- 🔧 Easy integration with IBSheet library
- ⚡ Automatic initialization and cleanup
- 🎯 TypeScript support
- 🔄 Data synchronization support
- 📤 Event emission for sheet instance access
- 🎨 Customizable styling
- 🚀 Standalone component (Angular 14+)

## Installation

Make sure you have IBSheet library loaded in your project before using this component.

Using npm:

```bash
npm install @ibsheet/angular
```

Using yarn:

```bash
yarn add @ibsheet/angular
```

## Usage

### Basic Usage

```typescript
import { Component } from "@angular/core";
import { IBSheetAngular, type IBSheetOptions } from "@ibsheet/angular";

@Component({
  selector: "app-example",
  standalone: true,
  imports: [IBSheetAngular],
  template: `
    <div>
      <ibsheet-angular [options]="sheetOptions" [data]="sheetData"> </ibsheet-angular>
    </div>
  `,
})
export class ExampleComponent {
  sheetOptions: IBSheetOptions = {
    Cfg: {
      SearchMode: 2,
      HeaderMerge: 3,
    },
    Cols: [
      { Header: "ID", Type: "Text", Name: "sId" },
      { Header: "Name", Type: "Text", Name: "name" },
      { Header: "Age", Type: "Int", Name: "age" },
    ],
  };

  sheetData = [
    { sId: "1", name: "John Doe", age: 30 },
    { sId: "2", name: "Jane Smith", age: 25 },
  ];
}
```

Example: https://stackblitz.com/edit/stackblitz-starters-e5wa2tt7

### Advanced Usage with Event Handling

```typescript
import { Component } from "@angular/core";
import { 
  IBSheetAngular, 
  IB_Preset, 
  type IBSheetInstance, 
  type IBSheetOptions, 
  type IBSheetEvents 
} from "@ibsheet/angular";

const handleAfterChange: IBSheetEvents['onAfterChange'] = (param) => { 
  // The type of the parameter is automatically inferred.
  console.log('Data changed value:', param.val); 
};

@Component({
  selector: "app-advanced",
  standalone: true,
  imports: [IBSheetAngular],
  template: `
    <div>
      <div>
        <button (click)="handleAddRow()">Add Row</button>
        <button (click)="handleExportExcel()">Export Excel</button>
      </div>

      <ibsheet-angular [options]="sheetOptions" [data]="sheetData" [sync]="false" [style]="customStyle" (instance)="getInstance($event)"> </ibsheet-angular>
    </div>
  `,
})
export class AdvancedComponent {
  private mySheet: IBSheetInstance | undefined;

  sheetOptions: IBSheetOptions = {
    // Your IBSheet configuration options
    Cfg: {
      SearchMode: 2,
      HeaderMerge: 3,
    },
    Cols: [
      { Header: "ID", Type: "Text", Name: "sId" },
      { Header: "Name", Type: "Text", Name: "name" },
      { Header: "Age", Type: "Int", Name: "age" },
      { Header: "Ymd", Name: "sDate_Ymd", Extend: IB_Preset.YMD, Width: 110 }
    ],
    Events: {
      onAfterChange: handleAfterChange
    }
  };

  sheetData = [
    // Your data
    { sId: '1', name: 'John Doe', age: 30, sDate_Ymd: '20250923' },
    { sId: '2', name: 'Jane Smith', age: 25, sDate_Ymd: '20251002' }
  ];

  customStyle = {
    width: "100%",
    height: "600px",
    border: "1px solid #ccc",
  };

  getInstance(sheet: IBSheetInstance): void {
    // You can store the sheet instance or perform initial operations
    this.mySheet = sheet;
  }

  handleAddRow(): void {
    if (this.mySheet) {
      this.mySheet.addRow();
    }
  }

  handleExportExcel(): void {
    if (this.mySheet) {
      // exportData method requires the jsZip library
      // When checking for the jsZip library, if it hasn't been loaded separately, the file at ./plugins/jszip.min.js (relative to ibsheet.js) will be loaded automatically.
      this.mySheet.exportData({fileName:'ibsheet_angular_export_example.xlsx'});
    }
  }
}
```

Example: https://stackblitz.com/edit/stackblitz-starters-y4wxdjox

### Reuse existing IBSheet instances

```typescript
@Component({
  template: ` <ibsheet-angular [exgSheet]="existingSheet" [style]="sheetStyle"> </ibsheet-angular> `,
})
export class ReuseExampleComponent {
  existingSheet?: IBSheetInstance;

  constructor() {
    // Reuse IBSheet instances created elsewhere
    this.existingSheet = someExistingSheetInstance;
  }
}
```

## Input Properties

| Property   | Type              | Required | Default                              | Description                        |
| ---------- | ----------------- | -------- | ------------------------------------ | ---------------------------------- |
| `options`  | `IBSheetOptions`  | ✅       | -                                    | IBSheet configuration options      |
| `data`     | `any[]`           | ❌       | `[]`                                 | Initial data for the spreadsheet   |
| `sync`     | `boolean`         | ❌       | `false`                              | Enable data synchronization        |
| `style`    | `any`             | ❌       | `{ width: '100%', height: '800px' }` | Container styling object           |
| `exgSheet` | `IBSheetInstance` | ❌       | -                                    | Existing IBSheet instance to reuse |

## Output Events

| Event      | Type                | Description                                            |
| ---------- | ------------------- | ------------------------------------------------------ |
| `instance` | `EventEmitter<any>` | Emitted when the IBSheet instance is created and ready |

## Component Lifecycle

The component follows Angular's lifecycle hooks:

1. **ngOnInit**: Validates required inputs and initializes component properties
2. **ngAfterViewInit**: Creates the container div and initializes the IBSheet
3. **ngOnDestroy**: Automatically disposes of the IBSheet instance to prevent memory leaks

## TypeScript Support

Define your IBSheet options interface:

```typescript
export interface IBSheetOptions {
  Cfg?: IBSheetProperties;
  Def?: object;
  Cols?: IBCol[];
  LeftCols?: IBCol[];
  RightCols?: IBCol[];
  Head?: any[];
  Foot?: any[];
  Solid?: any[];
  Filter?: any[];
  Events?: IBSheetEvents;
}
```

IBSheet interface: https://www.npmjs.com/package/@ibsheet/interface

## Standalone Component

This component is built as an Angular standalone component, making it easy to use without module declarations:

```typescript
import { IBSheetAngular } from '@ibsheet/angular';

@Component({
  // ...
  standalone: true,
  imports: [IBSheetAngular], // Direct import
})
```

## Error Handling

The component includes comprehensive error handling:

- **Input Validation**: Throws an error if required `options` input is not provided
- **Initialization Retry**: Retries IBSheet initialization up to 50 times (5 seconds total)
- **Safe Disposal**: Safely disposes of IBSheet instances with error catching
- **Console Logging**: Provides detailed error messages for debugging

### Default Styling

The component applies default dimensions of 100% width and 800px height.

## Module Integration (Traditional Modules)

If you're using traditional Angular modules instead of standalone components:

```typescript
import { NgModule } from "@angular/core";
import { IBSheetAngular } from "@ibsheet/angular";

@NgModule({
  imports: [IBSheetAngular], // Import the standalone component
  // ...
})
export class YourModule {}
```

## Important Notes

1. **IBSheet Library**: Ensure the IBSheet library is loaded in your application before this component initializes
2. **Unique IDs**: Each component instance generates unique container and sheet IDs to prevent conflicts
3. **Memory Management**: The component automatically cleans up resources on destroy
4. **Async Initialization**: The component handles asynchronous IBSheet loading with automatic retries

## Troubleshooting

### Component not initializing

- Verify IBSheet library is loaded before component initialization
- Check browser console for error messages
- Ensure `options` input contains valid IBSheet configuration

### IBSheet library not found

```
[initializeIBSheet] IBSheet Initialization Failed: Maximum Retry Exceeded
```

**Solutions:**

- Confirm IBSheet script is loaded in your `index.html`
- Check network requests to ensure IBSheet files are accessible
- Verify IBSheet version compatibility

### Performance optimization

- Use `sync: false` for large datasets
- Consider implementing virtual scrolling for very large data sets
- Use OnPush change detection strategy when possible

### Memory leaks

The component automatically handles cleanup, but ensure you:

- Don't hold references to the sheet instance after component destruction
- Remove any custom event listeners you've added

## Load the IBSheet Library

Using Including External Script

ex) in index.html

```html
<link rel="stylesheet" href="ibsheet_path/css/default/main.css" />

<script src="ibsheet_path/ibsheet.js"></script>
<script src="ibsheet_path/locale/ko.js"></script>
<script src="ibsheet_path/plugins/ibsheet-common.js"></script>
<script src="ibsheet_path/plugins/ibsheet-dialog.js"></script>
<script src="ibsheet_path/plugins/ibsheet-excel.js"></script>
```

Using IBSheetLoader

- reference: https://www.npmjs.com/package/@ibsheet/loader
- manual: https://ibsheet.github.io/loader-manual

## Local Setup of the IBSheet Library

- Install the IBSheet library in the project's `root/public` directory or a subdirectory within `root/public`
- If you are using the "Including External Script" method, set the path to the IBSheet library in `ibsheet_path`
- If you are using the "IBSheetLoader" method, set the path to the IBSheet library in `baseUrl`

## IBSheet Manual

https://docs.ibsheet.com/ibsheet/v8/manual/#docs/intro/1introduce

## Sample

- https://github.com/ibsheet/ibsheet-angular-sample.git
- https://github.com/ibsheet/loader-angular-guide-sample.git

## License

[MIT](./LICENSE)