import { Meta, ArgsTable, Story, Preview } from "@storybook/addon-docs/blocks";
import { action } from "@storybook/addon-actions";
import { linkTo } from "@storybook/addon-links";
import Vuetable from "../components/Vuetable.vue";
import CustomCell from "../components/cells/CustomCell.vue";
import CSS from "./vuetable-css.js";

<Meta title="custom-cells" component={Vuetable} />

# Custom Cells

Vue components can be used as the cell template by importing one and replacing
the name value with it. Below is an example of how a component needs to be set
up to be useable with vuetable-3.

```html
<script lang="ts">
  import { Component, Prop } from "vue-property-decorator";
  import { mixins } from "vue-class-component";
  import VuetableFieldMixin from "../../components/VuetableFieldMixin.vue";

  @Component({
    name: "CustomCell",
    components: {},
    mixins: [VuetableFieldMixin]
  })
  export default class CustomCell extends mixins() {
    /**
     * Indicate whether Field Component should render the "header" or "data"
     * template section.
     */
    @Prop({ default: false })
    isHeader!: boolean;

    /**
     * The title option from field definition object is passed via title prop.
     * You can simply use title prop to render column title if there is no
     * special need other than display the column title.
     */
    @Prop({ default: "" })
    title!: string;

    @Prop({ default: () => null })
    rowData!: string;

    @Prop({ default: -1 })
    rowIndex!: number;

    /**
     * The field definition object of this field. Remember that you can use
     * field definition object to hold additional data, parameters, or results.
     */
    @Prop({ default: () => null })
    rowField!: object;

    /**
     * The click event needs to be bound on the header to have it bubble up for
     * sorting purposes.
     */
    onHeaderClick(event: unknown) {
      this.$emit("click", event);
    }
  }
</script>

<template>
  <th v-if="isHeader" scope="col" @click="onHeaderClick">{{ title }}</th>
  <td v-else>{{ rowData.name }}</td>
</template>
```

<Preview>
  <Story name="CellComponent">
    {{
      components: { Vuetable },
      props: {
        fields: {
          default: () => [
            {
              name: CustomCell,
              title: "Name"
            },
            {
              name: "email",
              title: "Email Address"
            },
            {
              name: "phone",
              titleClass: "center aligned",
              dataClass: "center aligned"
            }
          ]
        }
      },
      template: `
      <vuetable
        api-url="https://my-json-server.typicode.com/mannyyang/vuetable-3/users"
        pagination-path=""
        data-path=""
        :fields="fields"
      >
      </vuetable>
      `
    }}
  </Story>
</Preview>

## Using a cutom cell with sort

<Preview>
  <Story name="CellComponentWithSort">
    {{
      components: { Vuetable },
      props: {
        css: {
          default: () => CSS
        },
        fields: {
          default: () => [
            {
              name: CustomCell,
              title: "Name",
              sortField: "name"
            },
            {
              name: "email",
              title: "Email Address"
            },
            {
              name: "phone",
              titleClass: "center aligned",
              dataClass: "center aligned"
            }
          ]
        }
      },
      template: `
      <vuetable
        api-url="https://my-json-server.typicode.com/mannyyang/vuetable-3/users"
        :css="css.table"
        :query-params="{
          page: '_page',
          sort: '_sort',
          perPage: '_limit',
          order: '_order'
        }"
        pagination-path=""
        data-path=""
        :fields="fields"
      >
      </vuetable>
      `
    }}
  </Story>
</Preview>

In order to use Vue components as the sort icon, you'll need to update the css
object that is passed to vuetable-3.

```js
// Imported as `CSS` found in code example above.

import SortIcon from "./SortIcon";

export default {
  table: {
    tableWrapper: "",
    tableHeaderClass: "fixed",
    tableBodyClass: "fixed",
    ...,
    // When using the `renderSortComp` to use a component for the sort icon,
    // the css strings needs to be cleared out or else it'll add the `<i>` as an
    // html string.
    renderIcon: () => "",
    // Vue component will automatically pass the current order through `order`
    // prop.
    renderSortComp: SortIcon
  },

  pagination: {
    ...
  },

  paginationInfo: {
    ...
  }
};
```

The custom cell component needs to insert a slot to indicate where the sort icon
is going to be.

```html
// CustomCell.vue

<template>
  <th v-if="isHeader" @click="onHeaderClick">
    {{ title }}
    <slot />
  </th>
  <td v-else>Row cell data</td>
</template>
```

## Using an Initial Sort Order

You set the initial sort and order through the sort order property. Although it
takes an array as a property, we currently only support sorting by one column.

<Preview>
  <Story name="CellComponentWithInitialSort">
    {{
      components: { Vuetable },
      props: {
        css: {
          default: () => CSS
        },
        fields: {
          default: () => [
            {
              name: CustomCell,
              title: "Name",
              sortField: "name"
            },
            {
              name: "email",
              title: "Email Address",
              sortField: "email"
            },
            {
              name: "phone",
              titleClass: "center aligned",
              dataClass: "center aligned"
            }
          ]
        }
      },
      template: `
      <vuetable
        api-url="https://my-json-server.typicode.com/mannyyang/vuetable-3/users"
        :css="css.table"
        :query-params="{
          page: '_page',
          sort: '_sort',
          perPage: '_limit',
          order: '_order'
        }"
        :sort-order="[
          {
            sortField: 'email',
            direction: 'desc'
          }
        ]"
        pagination-path=""
        data-path=""
        :fields="fields"
      >
      </vuetable>
      `
    }}
  </Story>
</Preview>

