> ## Documentation Index
> Fetch the complete documentation index at: https://help.csvbox.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Install the Code

> Add a snippet of code to your app to start accepting spreadsheets from your users.

Embed the CSVbox importer in your app with a short code snippet. Go to the **Code** tab of the sheet, find the integration code, and place it in your application where you want the import button to appear.

## Install the importer

<Tabs>
  <Tab title="JavaScript">
    Sample code with basic usage:

    ```javascript theme={null}
    <button class="btn btn-primary" data-csvbox disabled onclick="importer.openModal();">Import</button>
    <script type="text/javascript" src="https://js.csvbox.io/script.js"></script>
    <script type="text/javascript">
        function callback(result, data) {
            if(result){
                console.log("success");
                console.log(data.row_success + " rows uploaded");
                //custom code
            }else{
                console.log("fail");
                //custom code
            }
        }
        let importer = new CSVBoxImporter("YOUR_LICENSE_KEY_HERE",{
        }, callback);

        importer.setUser({
            user_id: "default123"
        })
    </script>
    ```

    <Note>
      Each sheet has a unique license key. Find it on the **Code** tab of the sheet page and pass it to the `CSVBoxImporter` function.
    </Note>
  </Tab>

  <Tab title="React">
    Install using npm:

    ```javascript theme={null}
    npm install @csvbox/react
    ```

    This gives you access to the `CSVBoxButton` component, which has the basic functionality of the importer. Import the `CSVBoxButton` component into your project.

    ```javascript theme={null}
    import { CSVBoxButton } from '@csvbox/react'
    ```

    Basic usage:

    ```javascript theme={null}
    <CSVBoxButton
      licenseKey="YOUR_LICENSE_KEY_HERE"
      user={{
        user_id: "default123"
      }}
      onImport={(result, data) => {
        if(result){
          console.log("success");
          console.log(data.row_success + " rows uploaded");
          //custom code
        }else{
          console.log("fail");
          //custom code
        }
      }}
      render={(launch, isLoading)=>{
              return <button disabled={isLoading} onClick={launch}>Upload file</button>;
          }}
    >
      Import
    </CSVBoxButton>
    ```

    <Note>
      Each sheet has a unique license key. Find it in the **Code** section of the sheet page and attach it to the `licenseKey` property of the `CSVBoxButton` component.

      The optional `render` property lets you pass in your own button to use in place of the standard CSVbox element.
    </Note>
  </Tab>

  <Tab title="Angular">
    Install using npm:

    ```javascript theme={null}
    npm install @csvbox/angular
    ```

    <Note>
      For Angular versions below 12, use `@csvbox/angular_8`. For Angular 12 and above, use `@csvbox/angular`.
    </Note>

    **Import**

    Add `CSVBoxAngularModule` to your module imports.

    ```javascript theme={null}
    import { CSVBoxAngularModule } from "@csvbox/angular";

    @NgModule({
      ...
      imports: [
        ...
        CSVBoxAngularModule
      ]
    })
    ```

    Once this is set up, you can import and access the `CSVBoxMethods` module in your app component file.

    It brings the `csvbox-button` component into your project. Example:

    ```text theme={null}
    <csvbox-button [licenseKey]="licenseKey" [imported]="imported.bind(this)" [user]="user">Import</csvbox-button>
    ```

    Basic usage:

    ```javascript theme={null}
    @Component({
      selector: 'app-root',
      template: `
        <csvbox-button
          [licenseKey]="licenseKey"
          [user]="user"
          [imported]="imported.bind(this)">
          Import
        </csvbox-button>
      `
    })

    export class AppComponent {

      title = 'example';
      licenseKey = 'YOUR_LICENSE_KEY_HERE';
      user = { user_id: 'default123' };

      imported(result: boolean, data: any) {
        if(result) {
          console.log("Sheet uploaded successfully");
          console.log(data.row_success + " rows uploaded");
        }else{
          console.log("There was some problem uploading the sheet");
        }
      }
    }
    ```

    <Note>
      Each sheet has a unique license key. Find it in the **Code** section of the sheet page and attach it to the `licenseKey` property of the `AppComponent`.
    </Note>

    **Styling the button**

    To style `<csvbox-button>` from within your parent component, make sure the parent component has `ViewEncapsulation.None`, then pass a class down to `<csvbox-button>`. You can then style the `button` one level down.

    ```javascript theme={null}
    import { Component, ViewEncapsulation } from '@angular/core';
    ```

    ```javascript theme={null}
    @Component({
      selector: 'app-root',
      template: `
        <csvbox-button
          [licenseKey]="licenseKey"
          [user]="user"
          [dynamicColumns]="dynamicColumns"
          [imported]="imported.bind(this)"
          class="csvbox-btn"
          >
          Import
        </csvbox-button>
      `,
      encapsulation: ViewEncapsulation.None,
      styles: [`
        .csvbox-btn button {
            background: #007bff;
            border-radius: 3px;
          }
      `],
    })
    export class AppComponent {
        //...
    }
    ```
  </Tab>

  <Tab title="Vue.js">
    Install using npm:

    ```javascript theme={null}
    npm install @csvbox/vuejs
    ```

    This gives you access to the `CSVBoxButton` component. Import the `CSVBoxButton` component into your project.

    ```javascript theme={null}
    import { CSVBoxButton } from '@csvbox/vuejs'
    ```

    Include `CSVBoxButton` in your Vue `components`, and you're ready to get started.

    Basic usage:

    ```javascript theme={null}
    <template>
      <div id="app">
        <CSVBoxButton
          :licenseKey="licenseKey"
          :user="user"
          :onImport="onImport">
          Upload File
        </CSVBoxButton>
      </div>
    </template>

    <script>
    import { CSVBoxButton } from '@csvbox/vuejs';

    export default {
      name: 'App',
      components: {
        CSVBoxButton,
      },
      data: () => ({
        licenseKey: 'YOUR_LICENSE_KEY_HERE',
        user: {
          user_id: 'default123',
        },
      }),
      methods: {
        onImport: function (result, data) {
           if(result){
              console.log("success");
              console.log(data.row_success + " rows uploaded");
              //custom code
          }else{
              console.log("fail");
              //custom code
          }
        }
      },
    }
    </script>
    ```

    <Note>
      Each sheet has a unique license key. Find it in the **Code** section of the sheet page and attach it to the `licenseKey` property of the `CSVBoxButton` component.
    </Note>

    **Implementation demos**

    * Vue2: [https://codesandbox.io/s/csvbox-vue2-plzl0q](https://codesandbox.io/s/csvbox-vue2-plzl0q)
    * Vue3: [https://codesandbox.io/s/csvbox-vue3-vuselr](https://codesandbox.io/s/csvbox-vue3-vuselr)
  </Tab>
</Tabs>

<Warning>
  If your app or database restricts access to an IP allowlist, you need to manually add CSVbox's addresses to use the importer. Allowlist all of the following IP addresses:

  * `18.233.84.183`
  * `18.213.249.53`
  * `3.73.26.144`

  Only one of these addresses is in use at any time, but the active address can change at any time. Add them all to your allowlist to avoid interruptions in service.
</Warning>

## Referencing the user

Configure **custom user attributes** in the installation code to identify the users on your platform and match them with their imports.

<Tabs>
  <Tab title="JavaScript">
    Pass custom user attributes as input parameters to the `setUser` method. The custom user attributes are pushed to your destination along with the uploaded data.

    `user_id` is the only mandatory custom attribute. Apart from `user_id`, you can add up to 4 custom attributes in the `<key>: <value>` format. Example:

    ```javascript theme={null}
     importer.setUser({
            user_id: "1a2b3c4d5e6f",
            team_id: "sales2",
            isAuthenticated: "true",
            permissionLevel: "admin",
            email: "abc@example.com"
        })
    ```
  </Tab>

  <Tab title="React">
    Pass custom user attributes as an object to the `user` property of the `CSVBoxButton` component. The custom user attributes are pushed to your destination along with the uploaded data.

    `user_id` is the only mandatory custom attribute. Apart from `user_id`, you can add up to 4 custom attributes in the `<key>: <value>` format. Example:

    ```javascript theme={null}
      user={{
                  user_id: "1a2b3c4d5e6f",
                  team_id: "sales2",
                  isAuthenticated: "true",
                  permissionLevel: "admin",
                  email: "abc@example.com"
      }}
    ```
  </Tab>

  <Tab title="Angular">
    Pass custom user attributes as an object to the `user` property of the `AppComponent`. The custom user attributes are pushed to your destination along with the uploaded data.

    `user_id` is the only mandatory custom attribute. Apart from `user_id`, you can add up to 4 custom attributes in the `<key>: <value>` format. Example:

    ```javascript theme={null}
      user={
                  user_id: "1a2b3c4d5e6f",
                  team_id: "sales2",
                  isAuthenticated: "true",
                  permissionLevel: "admin",
                  email: "abc@example.com"
     }
    ```
  </Tab>

  <Tab title="Vue.js">
    Pass custom user attributes as an object to the `user` property of the `CSVBoxButton` component. The custom user attributes are pushed to your destination along with the uploaded data.

    `user_id` is the only mandatory custom attribute. Apart from `user_id`, you can add up to 4 custom attributes in the `<key>: <value>` format. Example:

    ```javascript theme={null}
      user: {
                  user_id: "1a2b3c4d5e6f",
                  team_id: "sales2",
                  isAuthenticated: "true",
                  permissionLevel: "admin",
                  email: "abc@example.com"
      },
    ```
  </Tab>
</Tabs>

## Callback function

Once the user uploads a file, the importer returns the status of the import along with metadata describing the completed import. Data is returned in two variables, `result` and `data`:

* **`result`**: a boolean that is `true` if the import succeeds and `false` if it fails.
* **`data`**: JSON data as shown below.

```javascript theme={null}
  {
    "import_id": 79418895,
    "sheet_id": 575,
    "sheet_name": "Products Import",
    "destination_type": "webhook",
    "row_count": 100,
    "row_success": 98,
    "row_fail": 2,
    "import_status": "Partial",
    "import_starttime": 87987897897,
    "import_endtime": 90890890809,
    "original_filename": "example-1.csv",
    "raw_file": "https://file-download-link",
    "custom_fields": {
      "user_id": "Z1001"
    },
    "column_mappings": [
      { "Name": "Name" },
      { "SKU": "Product SKU" },
      { "Price": "Sale Price" },
      { "Quantity": "Inventory"},
      { "Image URL": "Img"}
    ]
  }
```

<Note>
  The `data` object is null if the import fails. You can also configure the importer to receive the entire file data in JSON format in the `data` object. [Learn more](/getting-started/3-receive-data#data-on-the-client-side).
</Note>

You can write custom code to handle the success or failure conditions on the client side.

<Tabs>
  <Tab title="JavaScript">
    The `result` and `data` variables are available in the `callback` function, which is triggered when the import completes.

    ```javascript theme={null}
    function callback(result, data) {
            if(result){
                console.log("success");
                console.log(data.row_success + " rows uploaded");
                //custom code
            }else{
                console.log("fail");
                //custom code
            }
        }
    ```
  </Tab>

  <Tab title="React">
    The `onImport` property of the `CSVBoxButton` component provides access to the `result` and `data` variables.

    ```javascript theme={null}
    onImport={(result, data) => {
      if (result) {
        console.log("success");
        console.log(data.row_success + " rows uploaded");
        //custom code
      } else {
        console.log("fail");
        //custom code
      }
    }}
    ```
  </Tab>

  <Tab title="Angular">
    The `imported` property provides access to the `result` and `data` variables through the specified callback function.

    ```javascript theme={null}
      imported(result: boolean, data: any) {
        if(result) {
          console.log("Sheet uploaded successfully");
          console.log(data.row_success + " rows uploaded");
        }else{
          console.log("There was some problem uploading the sheet");
        }
      }
    ```
  </Tab>

  <Tab title="Vue.js">
    The `onImport` property provides access to the `result` and `data` variables.

    ```javascript theme={null}
    onImport: function (result, data) {
           if(result){
              console.log("success");
              console.log(data.row_success + " rows uploaded");
              //custom code
          }else{
              console.log("fail");
              //custom code
          }
    }
    ```
  </Tab>
</Tabs>

## Options

These additional configuration options are available with the CSVbox importer.

| Option | Type | Default | What it does |
| - | - | - | - |
| <span id="max_rows" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`max_rows` | `number` | `null` | Maximum number of data rows a single file can import. Headers are not counted: a file with 101 rows whose first row is the header has 100 data rows. |
| <span id="max_rows_allow_submit" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`max_rows_allow_submit` | `boolean` | `true` | When a file has more rows than `max_rows`: if `true`, the user can submit the first `max_rows` rows; if `false`, the user can't submit any rows. |
| <span id="max_rows_custom_message" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`max_rows_custom_message` | `string` | `null` | Custom message shown when a file has more rows than `max_rows`. Shown only when `max_rows_allow_submit` is `false`. |
| <span id="min_rows" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`min_rows` | `number` | `null` | Minimum number of rows required for a single upload. |
| <span id="min_rows_custom_message" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`min_rows_custom_message` | `string` | `null` | Custom message shown when a file has fewer rows than `min_rows`. |
| <span id="language" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`language` | `string` | `null` | Importer frontend language. Overrides the default language set in the CSVbox dashboard. See [supported language codes](#supported-language-codes). |
| <span id="allow_invalid" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`allow_invalid` | `boolean` | `0` | Whether users can submit the file even if it has validation errors. |
| <span id="request_headers" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`request_headers` | `object` | `null` | Additional headers passed with each HTTP request, as `{ "Header-Name": "value" }` pairs. |
| <span id="dynamic_list_request_headers" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`dynamic_list_request_headers` | `object` | `null` | Additional headers passed with each request to the [dynamic list API](/dashboard-settings/validations#dynamic-list). |
| <span id="sample_template_url" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`sample_template_url` | `string` | `null` | URL from which end users download the sample CSV file. Use with `sample_template_button_text` to give each user a customized sample file. |
| <span id="sample_template_button_text" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`sample_template_button_text` | `string` | `null` | Text on the button that downloads the sample CSV file. |
| <span id="target_file_name" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`target_file_name` | `string` | `null` | Name of the file pushed to your destination. Applies only to the S3, FTP Server, and Google Sheets destinations. |
| <span id="upload_file_url" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`upload_file_url` | `string` | `null` | URL of a file to preload into the importer, so users don't have to upload one. The importer loads the data when the user clicks **Import**. |
| <span id="upload_file_worksheet_name" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`upload_file_worksheet_name` | `string` | `null` | Worksheet to load when the `upload_file_url` file has multiple tabs. |
| <span id="theme" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`theme` | `string` | `null` | Theme applied at runtime: `light`, `light-custom`, `dark`, or `dark-custom`. If not set, the theme from the sheet dashboard is used. |
| <span id="default_header_row" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`default_header_row` | `number` | `1` | Row auto-selected as the header on the **Header Selection** page. Rows are 1-indexed. |

<Accordion title="Supported language codes">
  | Value | Language |
  | - | - |
  | `en` | English |
  | `de` | German |
  | `fr` | French |
  | `es` | Spanish |
  | `nl` | Dutch |
  | `pt` | Portuguese |
  | `th` | Thai |
  | `pl` | Polish |
  | `ro` | Romanian |
  | `he` | Hebrew |
  | `ja` | Japanese |
  | `da` | Danish |
  | `tr` | Turkish |
  | `sk` | Slovak |
  | `hi` | Hindi |
  | `ms` | Bahasa Malaysia (Malay) |
  | `ru` | Russian |
  | `vi` | Vietnamese |
  | `ko` | Korean |
  | `id` | Bahasa Indonesia |
  | `ar-EG` | Egyptian Arabic |
  | `ur` | Urdu |
  | `zh-CN` | Chinese (Simplified) |
  | `zh-TW` | Chinese (Traditional) |
  | `bg` | Bulgarian |
  | `cs` | Czech |
  | `hu` | Hungarian |
  | `uk` | Ukrainian |
</Accordion>

The following examples set several of these options:

<Tabs>
  <Tab title="JavaScript">
    Pass additional options as input parameters to the `setOptions` method.

    ```javascript theme={null}
    importer.setOptions({
        max_rows: 50,
        language: 'de',
        request_headers: {
            "Content-Type": "application/json",
            "X-Access-Token": "71ab1d73a4d1319b260e9a0sdbdbc1c"
        },
        sample_template_url: 'https://files.myapp.com/user-18768',
        sample_template_button_text: 'Starter Template'
    })
    ```
  </Tab>

  <Tab title="React">
    Pass the additional options as an object to the `options` property of the `CSVBoxButton` component.

    ```javascript theme={null}
    options={{
        max_rows: 50,
        language: 'de',
        request_headers: {
            "Content-Type": "application/json",
            "X-Access-Token": "71ab1d73a4d1319b260e9a0sdbdbc1c"
        },
        sample_template_url: 'https://files.myapp.com/user-18768',
        sample_template_button_text: 'Starter Template'
    }}
    ```
  </Tab>

  <Tab title="Angular">
    Pass the additional options as an object to the `options` property of the `AppComponent`.

    ```javascript theme={null}
    options = {
        max_rows: 50,
        language: 'de',
        request_headers: {
            "Content-Type": "application/json",
            "X-Access-Token": "71ab1d73a4d1319b260e9a0sdbdbc1c"
        },
        sample_template_url: 'https://files.myapp.com/user-18768',
        sample_template_button_text: 'Starter Template'
    }
    ```
  </Tab>

  <Tab title="Vue.js">
    Pass the additional options as an object to the `options` property of the `CSVBoxButton` component.

    ```javascript theme={null}
    options: {
        max_rows: 50,
        language: 'de',
        request_headers: {
            "Content-Type": "application/json",
            "X-Access-Token": "71ab1d73a4d1319b260e9a0sdbdbc1c"
        },
        sample_template_url: 'https://files.myapp.com/user-18768',
        sample_template_button_text: 'Starter Template'
    },
    ```
  </Tab>
</Tabs>

## Events

These additional importer events and properties are available.

| Event | Angular name | Arguments | When it fires |
| - | - | - | - |
| <span id="onready" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`onReady` | `importerReady` | None | The importer is initialized and ready for use. Users can then click the **Import** button to open the importer modal dialog. |
| <span id="onloadstart" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`onLoadStart` | `loadStarted` | None | The importer iframe starts loading. In vanilla JavaScript, it fires only when [Lazy Load](#lazy-load) is activated; without Lazy Load, the iframe starts loading as soon as the importer is initialized. |
| <span id="onclose" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`onClose` | `closed` | None | The importer is closed. |
| <span id="onsubmit" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`onSubmit` | `submitted` | `data` (object) | The user clicks **Submit** to upload the validated file. `data` contains metadata about the import; see the [sample](#onsubmit-data-object-sample) below. |
| <span id="onimport" style={{ scrollMarginTop: "var(--scroll-mt, 7rem)" }} />`onImport` | `imported` | `result` (boolean), `data` (object) | All the data is pushed to the destination. `result` is `true` when the import succeeds and `false` when it fails; `data` contains metadata about the import. |

<Accordion title="onSubmit data object sample">
  ```json theme={null}
  {
    "import_id": 79418895,
    "sheet_id": 575,
    "sheet_name": "Products Import",
    "destination_type": "webhook",
    "row_count": 100,
    "import_starttime": 87987897897,
    "original_filename": "example-01.csv",
    "custom_fields": {
      "user_id": "Z1001"
    },
    "column_mappings": [
      {
        "Item": "Product Name"
      },
      {
        "SKU": "Product SKU"
      },
      {
        "Price": "Sale Price"
      },
      {
        "Quantity": "Inventory"
      },
      {
        "Image URL": "Img"
      }
    ]
  }
  ```
</Accordion>

The following examples listen to these events:

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    <button class="btn btn-primary" data-csvbox disabled onclick="importer.openModal();">Import</button>
    <script type="text/javascript" src="https://js.csvbox.io/script.js"></script>
    <script type="text/javascript">
           function callback(result, data) {
               if(result){
                   console.log("Sheet uploaded successfully");
                   console.log(data.row_success + " rows uploaded");
               }else{
                   console.log("There was some problem uploading the sheet");
               }
           }
           let importer = new CSVBoxImporter("YOUR_LICENSE_KEY_HERE",{}, callback);
           importer.setUser({
               user_id: 'default123'
           });

           importer.listen("onReady", function(){
            console.log("onReady");
           });

           importer.listen("onClose", function(){
            console.log("onClose");
           });

            importer.listen("onSubmit", function(data){
            console.log("onSubmit");
            console.log(data.import_id);
           });

    </script>
    ```
  </Tab>

  <Tab title="React">
    ```javascript theme={null}
    import React from "react";

    import { CSVBoxButton } from "@csvbox/react";

    const App = () => {
      return (
        <CSVBoxButton
          licenseKey="YOUR_LICENSE_KEY_HERE"
          lazy={true}
          user={{
            user_id: "default123"
          }}
          onImport={(result, data) => {
            if (result) {
              console.log("success");
              console.log(data.row_success + " rows uploaded");
              //custom code
            } else {
              console.log("fail");
              //custom code
            }
          }}
          loadStarted={() => {
            console.log("loadStarted");
          }}
          onReady={() => {
            console.log("onReady");
          }}
          onClose={() => {
            console.log("onclosed");
          }}
          onSubmit={(data) => {
            console.log("onSubmit");
            console.log(data.import_id);
          }}
        >
          Import
        </CSVBoxButton>
      );
    };

    export default App;
    ```
  </Tab>

  <Tab title="Angular">
    Angular uses the event names in the **Angular name** column of the table above.

    ```javascript theme={null}
    import { Component } from '@angular/core';

    @Component({
      selector: 'app-root',
      template: `
        <csvbox-button
          [licenseKey]="licenseKey"
          [user]="user"
          [dynamicColumns]="dynamicColumns"
          [imported]="imported.bind(this)"
          [closed]="closed.bind(this)"
          [submitted]="submitted.bind(this)"
          [importerReady]="importerReady.bind(this)">
          Import
        </csvbox-button>
      `
    })
    export class AppComponent {

      title = 'example';
      licenseKey = 'YOUR_LICENSE_KEY_HERE';
      user = { user_id: 'default123' };
      dynamicColumns = [
        {
          column_name: 'col2',
          type: 'text'
        }
      ];

      imported(result: boolean, data: any) {
        console.log("result", result, "data", data)
        if(result) {
          console.log("Sheet uploaded successfully");
          console.log(data.row_success + " rows uploaded");
        }else{
          console.log("There was some problem uploading the sheet");
        }
      }

      loadStarted() {
        console.log("loadStarted");
      }

      closed(){
        console.log("onClose");
      }

      importerReady(){
        console.log("onReady");
      }

      submitted(data: any){
        console.log("onSubmit");
        console.log(data.import_id);
      }
    }
    ```
  </Tab>

  <Tab title="Vue.js">
    ```javascript theme={null}
    <template>
      <div>
        <CSVBoxButton
          licenseKey="YOUR_LICENSE_KEY_HERE"
          :user="{ user_id: 'default123' }"
          :onImport="onImport"
          :onReady="onReady"
          :onClose="onClose"
          :onSubmit="onSubmit"
          >Import</CSVBoxButton>

      </div>
    </template>
    <script>

    import CSVBoxButton from './components/CSVBoxButton'

    export default {
      name: 'App',
      components: {
        CSVBoxButton
      },
      methods: {
        onImport(result, data){
          console.log("onImport", result, data);
          if(result){
            console.log("success");
            console.log(data.row_success + " rows uploaded");
            //custom code
          }else{
            console.log("fail");
            //custom code
          }
        },
        onReady(){
          console.log("onReady");
        },
        onClose(){
          console.log("onClose");
        },
         onSubmit(data){
          console.log("onSubmit");
          console.log(data.import_id);
        }
      },
      mounted() {

      },
    }
    </script>
    ```
  </Tab>
</Tabs>

## Other settings

### Lazy load

The importer assets load when the webpage loads. This can slow your app if you initialize multiple importers on the same page. As a workaround, defer loading the importer assets until the **Import** button is clicked by adding the `lazy: true` parameter to the initialization code.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    let importer = new CSVBoxImporter("YOUR_LICENSE_KEY_HERE",{
        }, callback, { lazy: true });

    ```
  </Tab>

  <Tab title="React">
    ```javascript theme={null}
    import { CSVBoxButton } from '@csvbox/react'
    import './App.css';

    function App() {
      return (
        <div className="App">
          <CSVBoxButton
            licenseKey="YOUR_LICENSE_KEY_HERE"
            user={{
              user_id: "default123"
            }}
            onImport={(result, data) => {
              if(result){
                console.log("success");
                console.log(data.row_success + " rows uploaded");
                //custom code
              }else{
                console.log("fail");
                //custom code
              }
            }}
            lazy={true}
          >
            Import
          </CSVBoxButton>
        </div>
      );
    }

    export default App;
    ```
  </Tab>

  <Tab title="Angular">
    ```javascript theme={null}
    @Component({
      selector: 'app-root',
      template: `
        <csvbox-button
          [licenseKey]="licenseKey"
          [user]="user"
          [imported]="imported.bind(this)"
          [lazy]="lazy">
          Import
        </csvbox-button>
      `
    })
    export class AppComponent {
      title = 'csvbox-test';
      licenseKey = 'YOUR_LICENSE_KEY_HERE';
      user = { user_id: 'default123' };
      lazy = true;
      imported(result: boolean, data: any) {
        if(result) {
          console.log("Sheet uploaded successfully");
          console.log(data.row_success + " rows uploaded");
        }else{
          console.log("There was some problem uploading the sheet");
        }
      }
    }
    ```
  </Tab>

  <Tab title="Vue.js">
    ```javascript theme={null}
    <CSVBoxButton
          :licenseKey="licenseKey"
          :user="user"
          :onImport="onImport"
          :lazy="true">
          Upload File
    </CSVBoxButton>
    ```
  </Tab>
</Tabs>

## Next steps

<CardGroup cols={2}>
  <Card title="3. Receive Data" icon="inbox" href="/getting-started/3-receive-data">
    Receive the imported data in your app.
  </Card>

  <Card title="Destinations" icon="share-nodes" href="/destinations">
    Choose where CSVbox sends the imported data.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.