Categories
Buefy

Buefy — Sorting Multiple Columns and Row Details

Buefy is a UI framework that’s based on Bulma.

In this article, we’ll look at how to use Buefy in our Vue app.

Sorting Multiple Columns

We can enable the sorting of multiple columns with the sort-multiple prop.

For instance, we can write:

<template>
  <div id="app">
    <b-table :data="data" :columns="columns" sort-multiple></b-table>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    const data = [
      {
        id: 1,
        first_name: "james",
        last_name: "smith"
      },
      {
        id: 2,
        first_name: "mary",
        last_name: "jones"
      },
      {
        id: 3,
        first_name: "alex",
        last_name: "wong"
      }
    ];
    return {
      data,
      columns: [
        {
          field: "id",
          label: "ID",
          width: "40",
          numeric: true
        },
        {
          field: "first_name",
          label: "First Name",
          sortable: true
        },
        {
          field: "last_name",
          label: "Last Name",
          sortable: true
        }
      ]
    };
  }
};
</script>

to enable sorting the first name and last name columns with the sortable property set to true .

We can set the sorting priority of the column with the sort-multiple prop:

<template>
  <div id="app">
    <b-table :data="data" :columns="columns" :sort-multiple-data="sortingPriority" sort-multiple></b-table>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    const data = [
      {
        id: 1,
        first_name: "james",
        last_name: "smith"
      },
      {
        id: 2,
        first_name: "mary",
        last_name: "jones"
      },
      {
        id: 3,
        first_name: "alex",
        last_name: "wong"
      }
    ];
    return {
      data,
      sortingPriority: [
        { field: "first_name", order: 1 },
        { field: "last_name", order: 2 }
      ],
      columns: [
        {
          field: "id",
          label: "ID",
          width: "40",
          numeric: true
        },
        {
          field: "first_name",
          label: "First Name",
          sortable: true
        },
        {
          field: "last_name",
          label: "Last Name",
          sortable: true
        }
      ]
    };
  }
};
</script>

We set the value of the prop to an array with objects with the field and order properties to set the sorting priority.

Detailed Rows

We can add rows with details with the detail slot. To do that, we can write:

<template>
  <div id="app">
    <b-table
      :data="data"
      :columns="columns"
      detailed
      detail-key="id"
      ref="table"
      @details-open="(row) => $buefy.toast.open(`Expanded ${row.first_name}`)"
    >
      <b-table-column field="first_name" label="First Name" sortable v-slot="props">
        <template v-if="showDetailIcon">{{ props.row.first_name }}</template>
        <template v-else>
          <a @click="toggle(props.row)">{{ props.row.first_name }}</a>
        </template>
      </b-table-column>

      <b-table-column
        field="last_name"
        label="Last Name"
        sortable
        v-slot="props"
      >{{ props.row.last_name }}</b-table-column>

<template slot="detail" slot-scope="props">
        <article class="media">
          <div class="media-content">
            <div class="content">
              <p>
                <strong>{{ props.row.first_name }} {{ props.row.last_name }}</strong>
              </p>
            </div>
          </div>
        </article>
      </template>
    </b-table>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    const data = [
      {
        id: 1,
        first_name: "james",
        last_name: "smith"
      },
      {
        id: 2,
        first_name: "mary",
        last_name: "jones"
      },
      {
        id: 3,
        first_name: "alex",
        last_name: "wong"
      }
    ];
    return {
      data,
      columns: [
        {
          field: "id",
          label: "ID",
          width: "40",
          numeric: true
        },
        {
          field: "first_name",
          label: "First Name"
        },
        {
          field: "last_name",
          label: "Last Name"
        }
      ]
    };
  },
  methods: {
    toggle(row) {
      this.$refs.table.toggleDetails(row);
    }
  }
};
</script>

In the b-table-column components, we have the a tag which we can click to call toggle to toggle the detail pane on and off.

toggle takes the row , and calls this.$refs.table.toggleDetails(row) method to toggle the detail pane.

The details-open event is emitted whenever we toggle the details pane on.

Conclusion

We can add sorting to multiple columns and toggle details for a row.

Categories
Buefy

Buefy — Customize Table

Buefy is a UI framework that’s based on Bulma.

In this article, we’ll look at how to use Buefy in our Vue app.

Checkable Rows

We can add the checkable prop to make the rows checkable.

To do that, we write:

<template>
  <div id="app">
    <b-table
      :data="data"
      :columns="columns"
      :checked-rows.sync="checkedRows"
      :is-row-checkable="(row) => row.id !== 3 "
      checkable
      checkbox-position="left"
    >
      <template slot="bottom-left">
        <b>Total checked</b>
        : {{ checkedRows.length }}
      </template>
    </b-table>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    const data = [
      {
        id: 1,
        first_name: "james",
        last_name: "smith"
      },
      {
        id: 2,
        first_name: "mary",
        last_name: "jones"
      },
      {
        id: 3,
        first_name: "alex",
        last_name: "wong"
      }
    ];
    return {
      checkedRows: [],
      data,
      columns: [
        {
          field: "id",
          label: "ID",
          width: "40",
          numeric: true
        },
        {
          field: "first_name",
          label: "First Name"
        },
        {
          field: "last_name",
          label: "Last Name"
        }
      ]
    };
  }
};
</script>

The checkbox-position sets the checkbox position.

is-row-checkable lets us set which rows are checkable with a function. The row parameter is a row object we check.

checked-rows has an array of checked rows.

Searchable

We can add the searchable property to our column objects to make the column searchable.

For example, we can write:

<template>
  <div id="app">
    <b-table :data="data">
      <template v-for="column in columns">
        <b-table-column :key="column.id" v-bind="column">
          <template slot="searchable" slot-scope="props">
            <b-input v-model="props.filters[props.column.field]" placeholder="Search..."/>
          </template>
          <template v-slot="props">{{ props.row[column.field] }}</template>
        </b-table-column>
      </template>
    </b-table>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    const data = [
      {
        id: 1,
        first_name: "james",
        last_name: "smith"
      },
      {
        id: 2,
        first_name: "mary",
        last_name: "jones"
      },
      {
        id: 3,
        first_name: "alex",
        last_name: "wong"
      }
    ];
    return {
      checkedRows: [],
      data,
      columns: [
        {
          field: "id",
          label: "ID",
          width: "40",
          numeric: true
        },
        {
          field: "first_name",
          label: "First Name",
          searchable: true
        },
        {
          field: "last_name",
          label: "Last Name",
          searchable: true
        }
      ]
    };
  }
};
</script>

We will see a search box on any column that has the searchable property set to true .

The search box is added by populating the searchable slot with our own search box.

props.filters[props.column.field] is the search term that Buefy will look for.

Pagination and Sorting

We can add pagination with the paginated and per-page props:

<template>
  <div id="app">
    <b-table :data="data" :columns="columns" paginated :per-page="2"></b-table>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    const data = [
      {
        id: 1,
        first_name: "james",
        last_name: "smith"
      },
      {
        id: 2,
        first_name: "mary",
        last_name: "jones"
      },
      {
        id: 3,
        first_name: "alex",
        last_name: "wong"
      }
    ];
    return {
      data,
      columns: [
        {
          field: "id",
          label: "ID",
          width: "40",
          numeric: true
        },
        {
          field: "first_name",
          label: "First Name"
        },
        {
          field: "last_name",
          label: "Last Name"
        }
      ]
    };
  }
};
</script>

We add the paginated prop to enable pagination.

And we set the per-page prop to set the number of items per page.

To add sorting, we can add the default-sort prop and the sortable property to the column to make a column sortable:

<template>
  <div id="app">
    <b-table :data="data" :columns="columns" default-sort="first_name" default-sort-direction="asc"></b-table>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    const data = [
      {
        id: 1,
        first_name: "james",
        last_name: "smith"
      },
      {
        id: 2,
        first_name: "mary",
        last_name: "jones"
      },
      {
        id: 3,
        first_name: "alex",
        last_name: "wong"
      }
    ];
    return {
      data,
      columns: [
        {
          field: "id",
          label: "ID",
          width: "40",
          numeric: true
        },
        {
          field: "first_name",
          label: "First Name",
          sortable: true
        },
        {
          field: "last_name",
          label: "Last Name",
          sortable: true
        }
      ]
    };
  }
};
</script>

Conclusion

We can add pagination, make the rows checkable, and make columns sortable with Buefy.

Categories
Buefy

Buefy — Tables

Buefy is a UI framework that’s based on Bulma.

In this article, we’ll look at how to use Buefy in our Vue app.

Table

Buefy comes with a table component. It can be used to display data responsively.

We can use the b-table to add a simple table to our Vue app:

<template>
  <div id="app">
    <b-table :data="data" :columns="columns"></b-table>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      data: [
        {
          id: 1,
          first_name: "james",
          last_name: "smith"
        },
        {
          id: 2,
          first_name: "mary",
          last_name: "jones"
        },
        {
          id: 3,
          first_name: "alex",
          last_name: "wong"
        }
      ],
      columns: [
        {
          field: "id",
          label: "ID",
          width: "40",
          numeric: true
        },
        {
          field: "first_name",
          label: "First Name"
        },
        {
          field: "last_name",
          label: "Last Name"
        }
      ]
    };
  }
};
</script>

The data prop has an array of data.

columns has the column definitions. The field property has the property name. label has the column label.

The width has the column width.

Custom Columns

We can add the b-table-column column to add the columns. For example, we can write:

<template>
  <div id="app">
    <b-table :data="data" :columns="columns">
      <b-table-column field="id" label="ID" width="40" numeric v-slot="props">{{ props.row.id }}</b-table-column>

    <b-table-column
        field="first_name"
        label="First Name"
        v-slot="props"
      >{{ props.row.first_name }}</b-table-column>

    <b-table-column field="last_name" label="Last Name" v-slot="props">{{ props.row.last_name }}</b-table-column>
    </b-table>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      data: [
        {
          id: 1,
          first_name: "james",
          last_name: "smith"
        },
        {
          id: 2,
          first_name: "mary",
          last_name: "jones"
        },
        {
          id: 3,
          first_name: "alex",
          last_name: "wong"
        }
      ],
      columns: [
        {
          field: "id",
          label: "ID",
          width: "40",
          numeric: true
        },
        {
          field: "first_name",
          label: "First Name"
        },
        {
          field: "last_name",
          label: "Last Name"
        }
      ]
    };
  }
};
</script>

We added the b-table-column to add the columns.

props.row has the row object.

Custom Table

b-table has many props that we can change.

For example, we can write:

<template>
  <div id="app">
    <b-table
      :data="data"
      :columns="columns"
      bordered
      striped
      narrowed
      hoverable
      loading
      focusable
      mobile-cards
    ></b-table>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      data: [
        {
          id: 1,
          first_name: "james",
          last_name: "smith"
        },
        {
          id: 2,
          first_name: "mary",
          last_name: "jones"
        },
        {
          id: 3,
          first_name: "alex",
          last_name: "wong"
        }
      ],
      columns: [
        {
          field: "id",
          label: "ID",
          width: "40",
          numeric: true
        },
        {
          field: "first_name",
          label: "First Name"
        },
        {
          field: "last_name",
          label: "Last Name"
        }
      ]
    };
  }
};
</script>

to add the props.

bordered adds the borders.

striped makes the rows striped.

narrowed makes the rows shorter.

hoverable makes the rows hoverable.

loading shows the loading indicator over the table.

focusable makes the table focusable.

mobile-cards makes the mobile cards.

Selection

We can set the selected prop to make a row highlightable.

For example, we can write:

<template>
  <div id="app">
    <b-table :data="data" :columns="columns" :selected.sync="selected"></b-table>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    const data = [
      {
        id: 1,
        first_name: "james",
        last_name: "smith"
      },
      {
        id: 2,
        first_name: "mary",
        last_name: "jones"
      },
      {
        id: 3,
        first_name: "alex",
        last_name: "wong"
      }
    ];
    return {
      selected: data[1],
      data,
      columns: [
        {
          field: "id",
          label: "ID",
          width: "40",
          numeric: true
        },
        {
          field: "first_name",
          label: "First Name"
        },
        {
          field: "last_name",
          label: "Last Name"
        }
      ]
    };
  }
};
</script>

We added the selected prop with the reference to the row we want to highlight. Then we’ll see that it’s highlighted.

Conclusion

Buefy comes with a b-table component to let us add a table to a Vue app.

Categories
Buefy

Buefy — Snackbar and Steppers

Buefy is a UI framework that’s based on Bulma.

In this article, we’ll look at how to use Buefy in our Vue app.

Snackbar

A snackbar is a simple popup component.

We call the this.$buefy.snackbar.open method to open it:

<template>
  <section>
    <button class="button is-medium" @click="snackbar">Launch snackbar</button>
  </section>
</template>

<script>
export default {
  methods: {
    snackbar() {
      this.$buefy.snackbar.open(`snackbar`);
    }
  }
};
</script>

We can add more options to it”

<template>
  <section>
    <button class="button is-medium" @click="snackbar">Launch snackbar</button>
  </section>
</template>

<script>
export default {
  methods: {
    snackbar() {
      this.$buefy.snackbar.open({
        duration: 5000,
        message: "<b>snackbar</b>",
        type: "is-danger",
        position: "is-bottom-left",
        actionText: "Undo",
        queue: false,
        onAction: () => {
          this.$buefy.toast.open({
            message: "Action pressed",
            queue: false
          });
        }
      });
    }
  }
};
</script>

duration sets how long it’s shown in milliseconds.

message sets the message text. It can include HTML.

type sets the color of the snackbar text.

position sets the position.

actionText sets the text of the action.

queue sets whether the snackbar should queue with other notices.

onAction is run when the action text is clicked.

Steps

Buefy comes with a stepper to display the steps that users should take.

For example, we can write:

<template>
  <section>
    <b-steps
      v-model="activeStep"
      :animated="isAnimated"
      :rounded="isRounded"
      :has-navigation="hasNavigation"
      :icon-prev="prevIcon"
      :icon-next="nextIcon"
      :label-position="labelPosition"
      :mobile-mode="mobileMode"
      icon-pack="fa"
    >
      <b-step-item step="1" label="First" :clickable="isStepsClickable">
        <h1 class="title has-text-centered">Account</h1>
      </b-step-item>

      <b-step-item
        step="2"
        label="Second"
        :clickable="isStepsClickable"
        :type="{'is-success': isProfileSuccess}"
      >
        <h1 class="title has-text-centered">Profile</h1>
      </b-step-item>

      <b-step-item step="3" :visible="showSocial" label="Social" :clickable="isStepsClickable">
        <h1 class="title has-text-centered">Social</h1>
      </b-step-item>

      <b-step-item
        :step="showSocial ? '4' : '3'"
        label="Finish"
        :clickable="isStepsClickable"
        disabled
      >
        <h1 class="title has-text-centered">Finish</h1>
      </b-step-item>

      <template v-if="customNavigation" slot="navigation" slot-scope="{previous, next}">
        <b-button
          outlined
          type="is-danger"
          icon-pack="fa"
          icon-left="arrow-circle-left"
          :disabled="previous.disabled"
          @click.prevent="previous.action"
        >Previous</b-button>
        <b-button
          outlined
          type="is-success"
          icon-pack="fa"
          icon-right="arrow-circle-right"
          :disabled="next.disabled"
          @click.prevent="next.action"
        >Next</b-button>
      </template>
    </b-steps>
  </section>
</template>

<script>
export default {
  data() {
    return {
      activeStep: 0,

      showSocial: false,
      isAnimated: true,
      isRounded: true,
      isStepsClickable: false,

      hasNavigation: true,
      customNavigation: false,
      isProfileSuccess: false,

      prevIcon: "arrow-circle-left",
      nextIcon: "arrow-circle-right",
      labelPosition: "bottom",
      mobileMode: "minimalist"
    };
  }
};
</script>

We add the b-steps component to add the steps.

b-step-item has the content that we display below the step number.

icon-prev has the icon for the previous button.

icon-next has the icon for the next button.

animated lets us enable or disable animation.

rounded lets us make the step icon rounded.

icon-pack sets the icon pack to use.

'fa' is for Font Awesome.

has-navigation enables or disables navigation buttons.

The icons are added by the link tag:

<link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
      integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN"
      crossorigin="anonymous"
    />

with the public/index.html.

The navigation slot lets us add our own navigation controls.

previous and next has the methods to let us go forward and backward.

disabled lets us know when to disable the nav buttons.

Conclusion

We can add notifications and steps display with Buefy.

Categories
Buefy

Buefy — Loading Placeholder and Sidebar

Buefy is a UI framework that’s based on Bulma.

In this article, we’ll look at how to use Buefy in our Vue app.

Skeleton Loading Placeholder

Buefy comes with a skeleton component that we can use as a placeholder to show when content is loading.

To add it, we can use the b-skeleton component:

<template>
  <section>
    <b-skeleton width="20%" animated></b-skeleton>
    <b-skeleton width="40%" animated></b-skeleton>
    <b-skeleton width="60%" animated></b-skeleton>
    <b-skeleton width="80%" animated></b-skeleton>
  </section>
</template>

<script>
export default {
  data() {
    return {};
  },
  methods: {}
};
</script>

width has the width of the bar as the percentage of the screen viewport.

animated makes it animated.

Also, we can add a circle placeholder with the circle prop:

<template>
  <section>
    <figure class="media-left">
      <p class="image is-64x64">
        <b-skeleton circle width="64px" height="64px"></b-skeleton>
      </p>
    </figure>
  </section>
</template>

<script>
export default {
  data() {
    return {};
  },
  methods: {}
};
</script>

Sidebar

We can add a sidebar with the b-sidebar component.

For instance, we can write:

<template>
  <section>
    <b-sidebar
      type="is-light"
      :fullheight="fullheight"
      :fullwidth="fullwidth"
      :overlay="overlay"
      :right="right"
      v-model="open"
    >
      <div class="p-1">
        <img src="https://picsum.photos/id/1/100/50" alt="logo">
        <b-menu>
          <b-menu-list label="Menu">
            <b-menu-item label="Info"></b-menu-item>
            <b-menu-item icon="settings">
              <template slot="label" slot-scope="props">Administrator
                <b-icon class="is-pulled-right" :icon="props.expanded ? 'menu-down' : 'menu-up'"></b-icon>
              </template>
              <b-menu-item label="Users"></b-menu-item>
              <b-menu-item>
                <template slot="label">Devices
                  <b-dropdown aria-role="list" class="is-pulled-right" position="is-bottom-left">
                    <b-icon icon="dots-vertical" slot="trigger"></b-icon>
                    <b-dropdown-item>action 1</b-dropdown-item>
                    <b-dropdown-item>action 2</b-dropdown-item>
                  </b-dropdown>
                </template>
              </b-menu-item>
            </b-menu-item>
          </b-menu-list>
          <b-menu-list label="Actions">
            <b-menu-item label="Logout"></b-menu-item>
          </b-menu-list>
        </b-menu>
      </div>
    </b-sidebar>
  </section>
</template>

<script>
export default {
  data() {
    return {
      open: true,
      overlay: true,
      fullheight: true,
      fullwidth: false,
      right: false
    };
  }
};
</script>

<style>
.p-1 {
  padding: 1em;
}
</style>

to add a sidebar with the b-sidebar component.

type sets the color style.

fullHeight makes it full height.

fullWidth makes it full width.

overlay add an overlay below the sidebar.

right makes it display on the right.

v-model controls the open state of the sidebar.

We can make it static with the position prop et to 'static' :

<template>
  <section>
    <b-sidebar
      position="static"
      :fullheight="fullheight"
      :fullwidth="fullwidth"
      :right="right"
      v-model="open"
    >
      <div class="p-1">
        <img src="https://picsum.photos/id/1/100/50" alt="logo">
        <b-menu>
          <b-menu-list label="Menu">
            <b-menu-item label="Info"></b-menu-item>
            <b-menu-item icon="settings">
              <template slot="label" slot-scope="props">Administrator
                <b-icon class="is-pulled-right" :icon="props.expanded ? 'menu-down' : 'menu-up'"></b-icon>
              </template>
              <b-menu-item label="Users"></b-menu-item>
              <b-menu-item>
                <template slot="label">Devices
                  <b-dropdown aria-role="list" class="is-pulled-right" position="is-bottom-left">
                    <b-icon icon="dots-vertical" slot="trigger"></b-icon>
                    <b-dropdown-item>action 1</b-dropdown-item>
                    <b-dropdown-item>action 2</b-dropdown-item>
                  </b-dropdown>
                </template>
              </b-menu-item>
            </b-menu-item>
          </b-menu-list>
          <b-menu-list label="Actions">
            <b-menu-item label="Logout"></b-menu-item>
          </b-menu-list>
        </b-menu>
      </div>
    </b-sidebar>
  </section>
</template>

<script>
export default {
  data() {
    return {
      open: true,
      overlay: true,
      fullheight: true,
      fullwidth: false,
      right: false
    };
  }
};
</script>

<style>
.p-1 {
  padding: 1em;
}
</style>

Conclusion

We can add placeholders to show when content is loading and a sidebar with Buefy.