Categories
Buefy

Buefy — Autocomplete and Checkbox

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.

Autocomplete with Async Data

We can use autocomplete with async data.

For example, we can write:

<template>
  <section>
    <b-field label="Find a movie">
      <b-autocomplete
        :data="data"
        placeholder="Enter movie name"
        field="title"
        :loading="isFetching"
        @typing="getAsyncData"
        @select="option => selected = option"
      >
        <template slot-scope="props">
          <div class="media">
            <div class="media-content">{{ props.option.title }}</div>
          </div>
        </template>
      </b-autocomplete>
    </b-field>
    <p class="content">
      <b>Selected:</b>
      {{ selected }}
    </p>
  </section>
</template>

<script>
import debounce from "lodash/debounce";

export default {
  data() {
    return {
      data: [],
      selected: null,
      isFetching: false
    };
  },
  methods: {
    getAsyncData: debounce(async function(name) {
      if (!name.length) {
        this.data = [];
        return;
      }
      const res = await fetch(
        `https://api.themoviedb.org/3/search/movie?api_key=7edf1637e548d0c13892dab0a654d476&query=${name}`
      );
      const { results } = await res.json();
      this.data = results;
    }, 500)
  }
};
</script>

We listen to the typing event and call the getAsyncData method to get the data.

Async with Infinite Scroll

We can populate async data with infinite scroll.

For example, we can write:

<template>
  <section>
    <b-field label="Find a movie">
      <b-autocomplete
        :data="data"
        placeholder="movie"
        field="title"
        :loading="isFetching"
        :check-infinite-scroll="true"
        @typing="getAsyncData"
        @select="option => selected = option"
        @infinite-scroll="getAsyncData"
      >
        <template slot-scope="props">
          <div class="media">
            <div class="media-content">{{ props.option.title }}</div>
          </div>
        </template>
        <template slot="footer">
          <span v-show="page > totalPages" class="has-text-grey">No more movies found.</span>
        </template>
      </b-autocomplete>
    </b-field>
    <p class="content">
      <b>Selected:</b>
      {{ selected }}
    </p>
  </section>
</template>

<script>
import debounce from "lodash/debounce";

export default {
  data() {
    return {
      data: [],
      selected: null,
      isFetching: false,
      name: "",
      page: 1,
      totalPages: 1
    };
  },
  methods: {
    getAsyncData: debounce(async function(name) {
      if (this.page > this.totalPages) {
        return;
      }
      const res = await fetch(
        `https://api.themoviedb.org/3/search/movie?api_key=7edf1637e548d0c13892dab0a654d476&query=${name}&page=${
          this.page
        }`
      );
      const { results, total_pages } = await res.json();
      if (Array.isArray(results)) {
        this.data = [...this.data, ...results];
      }
      this.page++;
      this.totalPages = total_pages;
    }, 500)
  }
};
</script>

We added the infinite-scroll event listener to load more data when we scroll down the autocomplete list.

Checkbox

We can add a checkbox component with Buefy.

For example, we can write:

<template>
  <section>
    <div class="field">
      <b-checkbox v-model="checkbox">Basic</b-checkbox>
    </div>
  </section>
</template>

<script>
export default {
  data() {
    return {
      checkbox: false
    };
  }
};
</script>

We add a b-checkbox component with the v-model directive to bind it to the checkbox state.

Also, we can set the indeterminate prop to set make the checkbox accept an indeterminate value:

<template>
  <section>
    <div class="field">
      <b-checkbox indeterminate>Basic</b-checkbox>
    </div>
  </section>
</template>

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

Grouped Checkbox

We bind multiple checkbox to the same v-model value.

This way, we can have an array of selections in the checkbox.

For example, we can write:

<template>
  <section>
    <div class="block">
      <b-checkbox v-model="checkboxGroup" native-value="apple">apple</b-checkbox>
      <b-checkbox v-model="checkboxGroup" native-value="orange">orange</b-checkbox>
      <b-checkbox v-model="checkboxGroup" native-value="grape">grape</b-checkbox>
    </div>
    <p class="content">
      <b>Selection:</b>
      {{ checkboxGroup }}
    </p>
  </section>
</template>

<script>
export default {
  data() {
    return {
      checkboxGroup: ["apple"]
    };
  }
};
</script>

native-value has the value that we put in the checkboxGroup array.

When we check them off, we’ll see the checked items.

Conclusion

We can populate the autocomplete items asynchronously.

Also, we can add checkboxes with our own item

Categories
Buefy

Buefy — Dropdowns

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.

Dropdown

Buefy comes with its own dropdown component.

For example, we can add one by writing:

<template>
  <section>
    <b-dropdown aria-role="list">
      <button class="button is-primary" slot="trigger" slot-scope="{ active }">
        <span>Click me!</span>
        {{active ? '&#x2191;': '&#x2193;'}}
      </button>

<b-dropdown-item aria-role="listitem">foo</b-dropdown-item>
      <b-dropdown-item aria-role="listitem">bar</b-dropdown-item>
      <b-dropdown-item aria-role="listitem">baz</b-dropdown-item>
    </b-dropdown>
  </section>
</template>

<script>
export default {
  name: "App"
};
</script>

The trigger slot has the button to trigger the dropdown.

active indicates whether the dropdown is open or not.

We can add a right-click menu with:

<template>
  <section>
    <b-dropdown :triggers="['contextmenu']">
      <button class="button is-link" slot="trigger" role="button">Right click</button>

      <b-dropdown-item aria-role="listitem">foo</b-dropdown-item>
      <b-dropdown-item aria-role="listitem">bar</b-dropdown-item>
      <b-dropdown-item aria-role="listitem">baz</b-dropdown-item>
    </b-dropdown>
  </section>
</template>

<script>
export default {
  name: "App"
};
</script>

We set the triggers prop to [‘contextmenu’] to make it open on right-click.

Drop Down Content and Position

We can add the custom prop to put any kind of content into our dropdown items.

For example, we can write:

<template>
  <section>
    <b-dropdown>
      <button class="button is-link" slot="trigger" role="button">Click</button>

      <b-dropdown-item :focusable="false" custom paddingless>
        <form action>
          <div class="modal-card" style="width:300px;">
            <section class="modal-card-body">
              <b-field label="Email">
                <b-input type="email" placeholder="Your email" required></b-input>
              </b-field>

              <b-field label="Password">
                <b-input type="password" password-reveal placeholder="Your password" required></b-input>
              </b-field>
            </section>
            <footer class="modal-card-foot">
              <button class="button is-primary">Login</button>
            </footer>
          </div>
        </form>
      </b-dropdown-item>
    </b-dropdown>
  </section>
</template>

<script>
export default {
  name: "App"
};
</script>

We add the custom prop to our b-dropdown-item so that we can add a form into our dropdown as a dropdown item.

Links

Dropdown items can have links if we add the has-link prop to the item.

For example, we can write:

<template>
  <section>
    <b-dropdown>
      <button class="button is-link" slot="trigger" role="button">Click</button>

      <b-dropdown-item has-link>
        <a href="https://google.com" target="_blank">
          <b-icon icon="link"></b-icon>Google (link)
        </a>
      </b-dropdown-item>
      <b-dropdown-item value="home">
        <b-icon icon="home"></b-icon>Home
      </b-dropdown-item>
    </b-dropdown>
  </section>
</template>

<script>
export default {
  name: "App"
};
</script>

Customizing with v-model

We can add the v-model directive to control our dropdown menu programmatically.

For example, we can write:

<template>
  <section>
    <b-dropdown v-model="isPublic">
      <button class="button is-primary" type="button" slot="trigger">
        <template v-if="isPublic">
          <span>Public</span>
        </template>
        <template v-else>
          <span>Friends</span>
        </template>
      </button>

      <b-dropdown-item :value="true">
        <div class="media">
          <div class="media-content">
            <h3>Public</h3>
            <small>Everyone can see</small>
          </div>
        </div>
      </b-dropdown-item>

      <b-dropdown-item :value="false">
        <div class="media">
          <div class="media-content">
            <h3>Friends</h3>
            <small>Only friends can see</small>
          </div>
        </div>
      </b-dropdown-item>
    </b-dropdown>
  </section>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      isPublic: false
    };
  }
};
</script>

We can set the v-model to set the selected item.

The value prop is the value of the selected item.

Conclusion

We can create dropdown menus with various options with Buefy.

Categories
Buefy

Buefy — Confirm Dialog

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.

Confirm Dialog

We can add a cancel button with the confirm button with the cancelText property:

<template>
  <section>
    <button class="button is-primary" @click="confirm">Launch confirm</button>
  </section>
</template>

<script>
export default {
  name: "App",
  methods: {
    confirm() {
      this.$buefy.dialog.confirm({
        title: "Title",
        message: "Are you sure?",
        cancelText: "Disagree",
        confirmText: "Agree",
        onConfirm: () => this.$buefy.toast.open("confirmed")
      });
    }
  }
};
</script>

Also, we can add an icon with the type and iconPack properties:

<template>
  <section>
    <button class="button is-primary" @click="confirm">Launch confirm</button>
  </section>
</template>

<script>
export default {
  name: "App",
  methods: {
    confirm() {
      this.$buefy.dialog.confirm({
        title: "Title",
        message: "Are you sure?",
        confirmText: "Agree",
        type: "is-danger",
        iconPack: "fa",
        hasIcon: true,
        onConfirm: () => this.$buefy.toast.open("confirmed")
      });
    }
  }
};
</script>

iconPack sets the icon pack to use. 'fa' stands for Font Awesome.

is-danger is the icon class name.

hasIcon enables the icon to be displayed.

Prompt Dialog

Buefy also comes with its own prompt dialog box.

For example, we can write:

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

<script>
export default {
  name: "App",
  methods: {
    prompt() {
      this.$buefy.dialog.prompt({
        message: `What's your name?`,
        inputAttrs: {
          placeholder: "Enter name",
          maxlength: 10
        },
        trapFocus: true,
        onConfirm: value => this.$buefy.toast.open(`Your name is: ${value}`)
      });
    }
  }
};
</script>

We call the prompt method with a message and inputAttrs properties.

message has the message.

inputAttrs has placeholders and max length of the input.

The onConfirm method is called after the dialog is dismissed.

value has the value entered in the prompt input.

trapFocus focus on the prompt input when it’s opened.

We can also add a numeric prompt input:

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

<script>
export default {
  name: "App",
  methods: {
    prompt() {
      this.$buefy.dialog.prompt({
        message: `What's your age?`,
        inputAttrs: {
          placeholder: "Enter age",
          maxlength: 3,
          min: 18
        },
        trapFocus: true,
        onConfirm: value => this.$buefy.toast.open(`Your age is: ${value}`)
      });
    }
  }
};
</script>

maxlength restricts the length and min is the min value.

We can control how the dialog is closed.

For example, we can write:

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

<script>
export default {
  name: "App",
  methods: {
    prompt() {
      this.$buefy.dialog.prompt({
        message: `What's your age?`,
        inputAttrs: {
          placeholder: "Enter age"
        },
        trapFocus: true,
        onConfirm: (value, { close }) => {
          this.$buefy.toast.open(`Sending...`);
          setTimeout(() => {
            this.$buefy.toast.open(`Success`);
            close();
          }, 2000);
        }
      });
    }
  }
};
</script>

to call the close method on the onConfirm callback.

This way, we can close it when we want instead of closing it immediately.

Promise

The dialog methods also return a promise.

To do that, we set the defaultProgrammaticPromise to true when we call Vue.use .

For example, we can write:

main.js

import Vue from "vue";
import App from "./App.vue";
import Buefy from "buefy";
import "buefy/dist/buefy.css";
Vue.use(Buefy, {
  defaultProgrammaticPromise: true
});
Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App)
}).$mount("#app");

App.vue

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

<script>
export default {
  name: "App",
  methods: {
    async prompt() {
      await this.$buefy.dialog.prompt({
        message: `What's your age?`,
        inputAttrs: {
          placeholder: "Enter age"
        }
      });
      console.log("closed");
    }
  }
};
</script>

Now we see that the 'closed' string is logged after we closed the prompt.

Conclusion

We can add confirm dialogs with Buefy and configure it in various ways.

Categories
Buefy

Buefy — Collapse and Dialogs

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.

Collapse Accordion

We can change the collapse component to have an accordion effect.

For example, we can write:

<template>
  <section>
    <b-collapse
      animation="slide"
      v-for="(collapse, index) of collapses"
      :key="index"
      :open="isOpen === index"
      @open="isOpen = index"
    >
      <div slot="trigger" slot-scope="props" class="card-header" role="button">
        <p class="card-header-title">{{ collapse.title }}</p>
        <a class="card-header-icon">{{props.open ? '&#x2193;' : '&#x2191;'}}</a>
      </div>
      <div class="card-content">
        <div class="content">{{ collapse.text }}</div>
      </div>
    </b-collapse>
  </section>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      isOpen: 0,
      collapses: [
        {
          title: "Title 1",
          text: "Text 1"
        },
        {
          title: "Title 2",
          text: "Text 2"
        },
        {
          title: "Title 3",
          text: "Text 3"
        }
      ]
    };
  }
};
</script>

We have the b-collapse components with some props.

open determines the index of the collapse item to open.

animation has the animation effect.

The @open listener listens to clicks on a collapse and expands the one that’s clicked on and collapses the rest.

Also, we populate the trigger slot to populate the heading of the accordion item.

props.open determines which one is expanded.

Alert Dialog

Buefy comes with a dialog component.

To use it, we can write:

<template>
  <section>
    <button class="button is-primary" @click="alert">Launch alert</button>
  </section>
</template>

<script>
export default {
  name: "App",
  methods: {
    alert() {
      this.$buefy.dialog.alert("hello world!");
    }
  }
};
</script>

to display an alert when we click on the button.

We can add a title with the message.

For example, we can write:

<template>
  <section>
    <button class="button is-primary" @click="alert">Launch alert</button>
  </section>
</template>

<script>
export default {
  name: "App",
  methods: {
    alert() {
      this.$buefy.dialog.alert({
        title: "Title",
        message: "<b>hello world</b>",
        confirmText: "OK"
      });
    }
  }
};
</script>

We have an alert with a title and HTML content for the message.

The confirmText lets us set the confirmation text.

Also, we can add an icon to the alert.

For example, we can write:

<template>
  <section>
    <button class="button is-primary" @click="alert">Launch alert</button>
  </section>
</template>

<script>
export default {
  name: "App",
  methods: {
    alert() {
      this.$buefy.dialog.alert({
        title: "Title",
        message: "<b>error</b>",
        confirmText: "OK",
        type: "is-danger",
        hasIcon: true,
        icon: "times-circle",
        iconPack: "fa"
      });
    }
  }
};
</script>

to add an icon to our alert dialog.

icon and iconPack sets the icon classes that are added to the message.

Confirm Dialog

We can add a confirm dialog with the confirm method.

For example, we can write:

<template>
  <section>
    <button class="button is-primary" @click="confirm">Launch confirm</button>
  </section>
</template>

<script>
export default {
  name: "App",
  methods: {
    confirm() {
      this.$buefy.dialog.confirm({
        message: "Are you sure?",
        onConfirm: () => this.$buefy.toast.open("confirmed")
      });
    }
  }
};
</script>

We call the confirm method with an object to set the message and an onConfirm callback that’s run after we click the button to dismiss it.

Also, we can add a title with the message:

<template>
  <section>
    <button class="button is-primary" @click="confirm">Launch confirm</button>
  </section>
</template>

<script>
export default {
  name: "App",
  methods: {
    confirm() {
      this.$buefy.dialog.confirm({
        title: "Title",
        message: "Are you sure?",
        onConfirm: () => this.$buefy.toast.open("confirmed")
      });
    }
  }
};
</script>

Conclusion

We can add accordions and dialog boxes easily with Buefy.

Categories
Buefy

Getting Started with Buefy for Vue.js

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

In this article, we’ll look at how to install Buefy and use it.

Installation

We can install Buefy with NPM or Yarn.

To install it, we run:

npm install buefy

Then we add it to our Vue project’s main.js file:

import Vue from "vue";
import App from "./App.vue";
import Buefy from "buefy";
import "buefy/dist/buefy.css";

Vue.use(Buefy);
Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App)
}).$mount("#app");

We can also add the CSS and JS files in our HTML file directly with:

<link rel="stylesheet" href="https://unpkg.com/buefy/dist/buefy.min.css">
<script src="https://unpkg.com/buefy/dist/buefy.min.js"></script>

Constructor Options

Buefy takes a few options for to configure it.

For example, we can write:

import Vue from "vue";
import App from "./App.vue";
import Buefy from "buefy";
import "buefy/dist/buefy.css";

Vue.use(Buefy, {
  defaultIconPack: "fas",
  defaultContainerElement: "#content"
  // ...
});
Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App)
}).$mount("#app");

defaultIconPack has the icons package name.

defaultIconcomponent has the container element to render the icon.

There are also many other properties listed at https://buefy.org/documentation/constructor-options.

Button

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

For example, we can use it by writing:

<template>
  <section>
    <b-button @click="clickMe">Click Me</b-button>
  </section>
</template>

<script>
export default {
  methods: {
    clickMe() {
      this.$buefy.notification.open("Clicked!!");
    }
  }
};
</script>

We have the clickMe method to show a notification when the button is clicked.

Button Types and States

We can set the type prop to set the button color.

For example, we can write:

<template>
  <section>
    <b-button type="is-primary">Primary</b-button>
    <b-button type="is-primary is-light">Primary Light</b-button>
  </section>
</template>

<script>
export default {};
</script>

is-primary changed the color to purple.

And is-light makes it lighter.

Other type values include is-success , is-danger , is-info , and is-link .

We can also add other props to a button.

disabled disables the button.

loading displays a loading spinner in the button.

focused makes it focused.

rounded makes it more rounded.

selected makes the button selected.

active makes it display as an active button.

For example, we can write:

<template>
  <section>
    <b-button focused>Primary</b-button>
  </section>
</template>

<script>
export default {};
</script>

to make the button focused.

Button Sizes

We can change the button size with the size prop.

For example, we can write:

<template>
  <section>
    <div class="buttons">
      <b-button size="is-small">Small</b-button>
      <b-button>Default</b-button>
      <b-button size="is-medium">Medium</b-button>
      <b-button size="is-large">Large</b-button>
    </div>
  </section>
</template>

<script>
export default {};
</script>

to set the button to various sizes.

Button Icons

We can add button icons to our buttons.

For example, we can use Font Awesome 4.7.0 icons by adding the CSS file into the head tag of main.html :

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

Then we can add our icon by writing:

<template>
  <section>
    <div class="buttons">
      <b-button size="is-small" icon-left="address-book">Add</b-button>
      <b-button icon-left="address-book">Add</b-button>
      <b-button size="is-medium" icon-left="address-book">Add</b-button>
      <b-button size="is-large" icon-left="address-book">Add</b-button>
    </div>
  </section>
</template>

<script>
export default {};
</script>

in main.js , we write:

import Vue from "vue";
import App from "./App.vue";
import Buefy from "buefy";
import "buefy/dist/buefy.css";

Vue.use(Buefy, {
  defaultIconPack: "fa"
});
Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App)
}).$mount("#app");

We add the icon-left prop with the icon name without the fa prefix.

The defaultIconPack is set to 'fa' to set the prefix.

Conclusion

Buefy is a useful UI library for Vue. We can add buttons easily with it.