Basic Usage

Create a catalog instance with a onFetch callback. Then, you need to initialize it either automatically or manually.

Depending on your requirements, build your component using the available API.

import { TText } from "@dija/tohama-components";
import { createCatalog } from "@dija/tohama-use";
import { defineComponent, onBeforeMount } from "vue";

export default defineComponent({
  setup() {
    // Create a new instance
    const { entries, init } = createCatalog<City, Filters>({
      /// options
      onFetch: (aggregates) => {
        ///
      },
    });

    // Auto initialize instance on component mount
    onBeforeMount(() => {
      init();
    });

    // Display the entries
    return () => (
      <div>
        {entries.value.map((entry) => (
          <TText>{entry.city}</TText>
        ))}
      </div>
    );
  },
});

Pagination

An example using other components such as t-pagination and t-loading.

Cities


Showing 0 of 0 cities.

import { createCatalog } from "@dija/tohama-use";
import { defineComponent, onBeforeMount } from "vue";

export default defineComponent({
  setup() {
    const catalog = createCatalog<City, Filters>({
      /// options
      aggregates: {
        limit: 4,
      },
      onFetch: (aggregates) => {
        ///
      },
    });

    onBeforeMount(() => catalog.init());

    return () => (
      <TCard design="flat" p>
        <TFlex justify="between" mb="sm">
          <TFlex align="center">
            <TIcon icon="mdi:map-marker" me="sm" />
            <TText size="xl" leading="tight">
              Cities
            </TText>
          </TFlex>
          {catalog.state.value === "loading" && <TLoading dimensions="24" width="3" />}
        </TFlex>

        <TDivider my="sm" />

        <TCell mb="sm">
          <TText size="md" weight="normal">
            Showing {catalog.entries.value.length} of {catalog.total.value} cities.
          </TText>
        </TCell>

        <TCard design="text" py="sm" mb="sm" elevated surface px>
          {catalog.entries.value.map((entry) => (
            <TFlex justify="between" py="sm">
              <TText size="re" leading="tight" color="danger">
                {entry.city}
              </TText>
              <TText size="re" leading="tight">
                {entry.country}
              </TText>
            </TFlex>
          ))}
        </TCard>

        <TPagination
          active-color="danger"
          count={catalog.pagesCount.value}
          value={catalog.page.value}
          onChange={(p) => catalog.loadPage(p)}
          stretch
        />
      </TCard>
    );
  },
});

Filter

An example with aggregates filtering and with infinite mode to display load more list.

Cities


import { createCatalog } from "@dija/tohama-use";
import { defineComponent, onBeforeMount } from "vue";

export default defineComponent({
  setup() {
    const catalog = createCatalog<City, Filters>({
      /// options
      mode: "infinite",
      aggregates: {
        limit: 6,
        page: 2,
      },
      onFetch: (aggregates) => {
        ///
      },
    });

    onBeforeMount(() => catalog.init());

    return () => (
      <TCard design="flat" p>
        <TFlex justify="between" mb="sm">
          <TFlex align="center">
            <TIcon icon="mdi:map-marker" me="sm" />
            <TText size="xl" leading="tight">
              Cities
            </TText>
          </TFlex>
          {catalog.state.value === "loading" && <TLoading dimensions="24" width="3" />}
        </TFlex>

        <TDivider my="sm" />

        <TFlex class="-mx-0.5 children:m-0.5" pb="md">
          <TButton
            design="raised"
            color="surface"
            size="sm"
            textColor={!catalog.aggregates.value.filter?.country ? "success" : "secondary"}
            onClick={() => catalog.filter({})}
            disabled={catalog.state.value === "loading"}
            elevated
          >
            All
          </TButton>
          <TButton
            design="raised"
            color="surface"
            size="sm"
            textColor={catalog.aggregates.value.filter?.country === "SA" ? "success" : "secondary"}
            onClick={() => catalog.filter({ country: "SA" })}
            disabled={catalog.state.value === "loading"}
            elevated
          >
            Saudi Arabia
          </TButton>
        </TFlex>

        <TButton
          design="flat"
          color="success"
          icon={catalog.hasPrevious.value ? "mdi:plus" : "mdi:check-all"}
          disabled={catalog.state.value === "loading" || !catalog.hasPrevious.value}
          onClick={catalog.loadPrevious}
          centered
          block
          mb
        >
          {catalog.hasPrevious.value ? `Load Previous` : "Finished!"}
        </TButton>

        <TCard class="min-h-40" design="text" py="sm" elevated surface px mb>
          {catalog.entries.value.map((entry) => (
            <TFlex justify="between" py="sm">
              <TText size="re" leading="tight" color="success">
                {entry.city}
              </TText>
              <TText size="re" leading="tight">
                {entry.country}
              </TText>
            </TFlex>
          ))}
        </TCard>

        <TButton
          design="flat"
          color="success"
          icon={catalog.hasNext.value ? "mdi:plus" : "mdi:check-all"}
          disabled={catalog.state.value === "loading" || !catalog.hasNext.value}
          onClick={catalog.loadNext}
          centered
          block
        >
          {catalog.hasNext.value ? `Load ${catalog.total.value - catalog.entries.value.length} Remaining` : "Finished!"}
        </TButton>
      </TCard>
    );
  },
});

Selection

An example with the selection functionality and cache enabled.

Cities


Selected 0 of 0 cities.

No entries found.

import { createCatalog } from "@dija/tohama-use";
import { defineComponent, onBeforeMount } from "vue";

export default defineComponent({
  setup() {
    const catalog = createCatalog<City, Filters>({
      /// options
      cache: true,
      aggregates: {
        limit: 4,
      },
      selection: {
        enabled: true,
      },
      getEntryKey: (entry) => entry.id,
      onFetch: (aggregates) => {
        ///
      },
    });

    onBeforeMount(() => catalog.init());

    return () => (
      <TCell>
        <TCard design="outlined" p>
          <TFlex justify="between" mb="sm">
            <TFlex align="center">
              <TIcon icon="mdi:map-marker" me="sm" />
              <TText size="xl" leading="tight">
                Cities
              </TText>
            </TFlex>
            <TFlex align="center">
              {catalog.state.value === "loading" && <TLoading dimensions="24" width="3" me="md" />}
              <TIconButton
                color="alert"
                design={catalog.selectable.value ? "flat" : "text"}
                icon={catalog.selectable.value ? "mdi:check-circle-outline" : "mdi:check-all"}
                onClick={catalog.toggleSelectable}
                me="sm"
              />
              <TIconButton
                color="danger"
                design={catalog.selectable.value ? "flat" : "text"}
                icon="mdi:trash-can"
                disabled={!catalog.selectable.value}
                onClick={() => {
                  for (const entry of catalog.selectedEntries.value) {
                    catalog.remove(entry);
                  }
                  catalog.toggleSelectable();
                }}
              />
            </TFlex>
          </TFlex>

          <TDivider my="sm" />

          <TCell mb="sm">
            <TText size="md" weight="normal" color={catalog.selected.value.length > 0 ? "alert" : "secondary"}>
              Selected {catalog.selected.value.length} of {catalog.total.value} cities.
            </TText>
          </TCell>

          <TCard design="outlined" mb="sm">
            {catalog.entries.value.map((entry) => (
              <TCard
                disabled={!catalog.selectable.value}
                rounded={false}
                onClick={() => catalog.toggleSelected(entry)}
                py="md"
                px
              >
                <TFlex justify="between" align="center">
                  <TIcon
                    size="20"
                    icon={
                      catalog.isSelected(entry) ? "mdi:checkbox-marked-circle" : "mdi:checkbox-blank-circle-outline"
                    }
                    me
                  />
                  <TCell stretch>
                    <TFlex justify="between" align="center">
                      <TText size="re" leading="tight" color="alert">
                        {entry.city}
                      </TText>
                      <TText size="sm" leading="tight">
                        {entry.country}
                      </TText>
                    </TFlex>
                  </TCell>
                </TFlex>
              </TCard>
            ))}
            {catalog.entries.value.length <= 0 && (
              <TText class="text-center" size="re" p>
                No entries found.
              </TText>
            )}
          </TCard>

          <TPagination
            active-color="alert"
            count={catalog.pagesCount.value}
            value={catalog.page.value}
            onChange={(p) => catalog.loadPage(p)}
            stretch
          />
        </TCard>
      </TCell>
    );
  },
});