Categories
Quasar

Developing Vue Apps with the Quasar Library — Rating Control Options

Quasar is a popular Vue UI library for developing good looking Vue apps.

In this article, we’ll take a look at how to create Vue apps with the Quasar UI library.

Rating Control Color

We can set the color of each icon with the color-selected prop:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <q-rating
          v-model="ratingModel"
          color="grey"
          size="3.5em"
          :color-selected="ratingColors"
        >
        </q-rating>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          ratingModel: 4.5,
          ratingColors: [
            "light-green-3",
            "light-green-6",
            "green",
            "green-9",
            "green-10"
          ]
        }
      });
    </script>
  </body>
</html>

We can set a different icon for half scores with he icon-half component:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <q-rating
          v-model="ratingModel"
          size="3.5em"
          color="yellow"
          icon="star_border"
          icon-selected="star"
          icon-half="star_half"
        >
        </q-rating>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          ratingModel: 4.5
        }
      });
    </script>
  </body>
</html>

We can disable dimming for unselected icons with the no-dimming prop:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <q-rating
          v-model="ratingModel"
          size="3.5em"
          color="yellow"
          icon="star_border"
          icon-selected="star"
          icon-half="star_half"
          no-dimming
        >
        </q-rating>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          ratingModel: 3.5
        }
      });
    </script>
  </body>
</html>

Rating Tooltip

We can set the tooltip for each rating by populating the slots for the tooltip content:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <q-rating v-model="ratingModel" size="3.5em" :max="3">
          <template v-slot:tip-1>
            <q-tooltip>Not bad</q-tooltip>
          </template>
          <template v-slot:tip-2>
            <q-tooltip>Good</q-tooltip>
          </template>
          <template v-slot:tip-3>
            <q-tooltip>Very good</q-tooltip>
          </template>
        </q-rating>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          ratingModel: 2
        }
      });
    </script>
  </body>
</html>

tip-1’s content is shown when we hover over the left star. tip-2 ‘s content is show when we hover over the 2nd to left star, etc.

Readonly and Disable

We can disable rating selection with the readonly or disable props:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <q-rating v-model="ratingModel" size="3.5em" :max="3" readonly>
        </q-rating>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          ratingModel: 2
        }
      });
    </script>
  </body>
</html>

Conclusion

We can add a rating component with various options into our Vue app with Quasar.

Categories
Quasar

Developing Vue Apps with the Quasar Library — Rating Control

Quasar is a popular Vue UI library for developing good looking Vue apps.

In this article, we’ll take a look at how to create Vue apps with the Quasar UI library.

Rating Control

We can add a rating control into our Vue app with the Quasarq-rating component.

For instance, we can write:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <q-rating v-model="ratingModel" size="1.5em" icon="thumb_up">
        </q-rating>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          ratingModel: 4.5
        }
      });
    </script>
  </body>
</html>

We bind the value to display to the ratingModel reactive property with v-model

size sets the size of the icon.

icon sets the name of the icon.

We can set the max rating score with the max prop:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <q-rating v-model="ratingModel" size="2em" :max="10" color="primary">
        </q-rating>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          ratingModel: 4.5
        }
      });
    </script>
  </body>
</html>

The icon for the rating display can also be an image:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <q-rating
          v-model="ratingModel"
          size="2em"
          color="primary"
          icon="img:https://cdn.quasar.dev/logo/svg/quasar-logo.svg"
        >
        </q-rating>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          ratingModel: 4.5
        }
      });
    </script>
  </body>
</html>

We can set an icon to display when the rating icon is selected with the icon-selected prop:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <q-rating
          v-model="ratingModel"
          size="3.5em"
          color="green-5"
          icon="star_border"
          icon-selected="star"
        >
        </q-rating>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          ratingModel: 4.5
        }
      });
    </script>
  </body>
</html>

We can also set each icon to a different one with the icon prop:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <q-rating
          v-model="ratingModel"
          size="3.5em"
          color="green-5"
          :icon="icons"
        >
        </q-rating>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          ratingModel: 4.5,
          icons: [
            "sentiment_very_dissatisfied",
            "sentiment_dissatisfied",
            "sentiment_satisfied",
            "sentiment_very_satisfied"
          ]
        }
      });
    </script>
  </body>
</html>

We set icon to an array of icon names.

Conclusion

We can add a rating control into our Vue app with Quasar.

Categories
Quasar

Developing Vue Apps with the Quasar Library — Popup Proxy and Pull to Refresh

Quasar is a popular Vue UI library for developing good looking Vue apps.

In this article, we’ll take a look at how to create Vue apps with the Quasar UI library.

Popup Proxy

We can use Quasar’s q-popup-proxy component to add a popup that’s triggered by clicking a button.

For instance, we can write:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <div class="q-pa-md">
          <q-btn push color="primary" label="button">
            <q-popup-proxy>
              <q-banner>
                <template v-slot:avatar>
                  <q-icon name="signal_wifi_off" color="primary" />
                </template>
                You are offline
              </q-banner>
            </q-popup-proxy>
          </q-btn>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {}
      });
    </script>
  </body>
</html>

We add it inside the button to make the popup display when we click the button.

The popup content is inside the q-popup-proxy ‘s default slot.

We can make the popup display when we right-click with the context-menu prop:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <div class="q-pa-md">
          <q-btn push color="primary" label="button">
            <q-popup-proxy context-menu>
              <q-banner>
                <template v-slot:avatar>
                  <q-icon name="signal_wifi_off" color="primary" />
                </template>
                You are offline
              </q-banner>
            </q-popup-proxy>
          </q-btn>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {}
      });
    </script>
  </body>
</html>

We can also make the popup trigger when we click on an icon that we have in the input with:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <div class="q-pa-md">
          <q-input filled v-model="input" mask="date" :rules="['date']">
            <template v-slot:append>
              <q-icon name="event" class="cursor-pointer">
                <q-popup-proxy :breakpoint="600">
                  <q-date v-model="input"></q-date>
                </q-popup-proxy>
              </q-icon>
            </template>
          </q-input>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          input: undefined
        }
      });
    </script>
  </body>
</html>

Pull to Refresh

We can add pull to refresh functionality with the q-pull-to-refresh component.

For instance, we can write:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <div class="q-pa-md">
          <div class="q-pa-md scroll" style="height: 300px;">
            <q-pull-to-refresh @refresh="refresh">
              <div v-for="n in num" :key="n" class="q-mb-sm">
                {{num - n}} - Lorem ipsum
              </div>
            </q-pull-to-refresh>
          </div>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          num: 50
        },
        methods: {
          refresh(done) {
            setTimeout(() => {
              this.num += 50;
              done();
            }, 1000);
          }
        }
      });
    </script>
  </body>
</html>

We have the items that we can pull to refresh inside tyhe q-pull-to-refresh component.

In the refresh handler, we call done when we’re done refreshing the content.

Conclusion

We can add popups and pull to refresh into our Vue app with Quasar.

Categories
Rxjs

Introduction to Reactive Programming with Rxjs

Rxjs is a reactive programming library that lets us use the observer pattern. This pattern lets us watch for changes in our programs and run code accordingly. Observables are the entities that emit values when it picks up changes. Observers are the entities that get the data sent by observables.

In this article, we’ll take a quick look at how to create new observables to send new values to observers.

Components of Rxjs

There’re a few parts to Rxjs. They are:

  • Observables — entities that get and send changes to observers
  • Observers — entities that watch for new data pushed from observables
  • Operators — functions that deal with collections with operations by using operations like like map, filter, concat, reduce, etc.
  • Subjects— event emitters that broadcast data to multiple observers
  • Schedulers — centralized dispatchers to control concurrency. They ley us coordinate when computation happens.

Creating Observables

We need observables to send data to observers. With Rxjs, we have an Observable constructor that lets us emit data with subscribers.

For example, we can write:

const observable = new Rx.Observable(subscriber => {
  subscriber.next(1);
  subscriber.next(2);
  setTimeout(() => {
    subscriber.next(3);
    subscriber.complete();
  }, 1000);
});

The observable above will emit 1, 2 immediately with the subscriber, and 3 after 1 second. The subscriber is the subscriber that we use to emit the data to the observers.

complete stops the observable from using the subscriber to emit more data.

We can use the observable to get the emitted values as follows:

observable.subscribe(val => console.log(val));

Also, we can pass in an object to the subscribe method with a next method for getting the emitted values, error for getting the errors, and the complete method to run something when the observable has done sending data:

observable.subscribe({
  next(x) {
    console.log(x);
  },
  error(err) {
    console.error(err);
  },
  complete() {
    console.log("done");
  }
});

Pull versus Push

Observables are push systems where data is pushed from a source that’s emitted from to the observer.

It’s a producer of multiple values. Evaluation is done only when observers get new values.

Observables are Like Functions

Observables are like functions in that they both return data for other entities. We can use the returned data in any place we wish.

For example, if we have the following function:

const foo = () => 1

and an observable:

const foo = new Observable(subscriber => {
  subscriber.next(1);
});

foo.subscribe(x => {
  console.log(x);
});

Then they both give us the value 1. Except that as we saw before, we can also get more than one value with observables which we can’t do with functions.

Also, they can either be synchronous or asynchronous like functions. From the first example, we have:

subscriber.next(1);
subscriber.next(2);

being run line by line, while:

setTimeout(() => {
  subscriber.next(3);
  subscriber.complete();
}, 1000);

waits 1 second before it runs, which means it’s asynchronous.

Parts of an Observable

Observables are created with the Obseravable constructor, which we can subscribe to with an observer.

It delivers next , error or complete notifications to observers. Observables are disposed of automatically once they received everything.

Creating an Observable

The Obserable constructor takes a callback function which has the subscriber parameter, which gets us the subscriber object to emit values.

For example, we can write:

const observable = new Observable((subscriber) => {
  const id = setInterval(() => {
    subscriber.next("foo");
  }, 1000);
});

to emit 'foo' every second to observers.

Subscribing to Observables

We call the subscribe method of the Observable object to subscribe to the values it pushes. For instance, we can write:

observable.subscribe(x => console.log(x));

to get the latest values.

The subscribe calls aren’t shared by multiple Observers of the same Observable. Each call to subscribe creates its own observer to observe the values.

Executing Observables

The code:

const observable = new Observable((subscriber) => {
  //...
});

executes the observable. It happens only for each Observable that subscribes.

It can deliver the following values:

  • next — sends values to observers
  • error — sends errors or exceptions to observers
  • complete — sends nothing

Observables adhere strictly to the Observable contract, so once complete is called, it’s not going to send more data.

For example:

const observable = new Observable(subscriber => {
  subscriber.next(1);
  subscriber.next(2);
  subscriber.next(3);
  subscriber.complete();
  subscriber.next(4);
});

4 won’t be sent to observables since complete has already been called.

Disposing Observable Executions

We can call the unsubscribe to stop subscribing to the observable. It’ll stop watching the Observable for more changes after it’s called and dispose of the resources needed to do the watching.

We can return an unsubscribe function to put clean up code that we want to add. For example, we can write:

const observable = new Observable(function subscribe(subscriber) {
  const intervalId = setInterval(() => {
    subscriber.next("hi");
  }, 1000);

  return function unsubscribe() {
    clearInterval(intervalId);
  };
});

const subscription = observable.subscribe(x => console.log(x));

setTimeout(() => {
  subscription.unsubscribe();
}, 3000);

The code above has an unsubscribe function that calls clearInterval with the ID returned by setInterval . Then we called subscribe to subscribe to our observable, which returns an object with the unsubscribe method. This method is called after 3 seconds in the callback for setTimeout .

With Rxjs, we can create Observables to emit values with the subscriber object. Then we can subscribe to observables to watch for values.

We can also create a function that cleans up when unsubscribing and call unsubscribe afterwards when we don’t want to subscribe to an Observable anymore.

Categories
Quasar

Developing Vue Apps with the Quasar Library — Popup Proxy and Pull to Refresh

Quasar is a popular Vue UI library for developing good looking Vue apps.

In this article, we’ll take a look at how to create Vue apps with the Quasar UI library.

Popup Proxy

We can use Quasar’s q-popup-proxy component to add a popup that’s triggered by clicking a button.

For instance, we can write:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <div class="q-pa-md">
          <q-btn push color="primary" label="button">
            <q-popup-proxy>
              <q-banner>
                <template v-slot:avatar>
                  <q-icon name="signal_wifi_off" color="primary" />
                </template>
                You are offline
              </q-banner>
            </q-popup-proxy>
          </q-btn>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {}
      });
    </script>
  </body>
</html>

We add it inside the button to make the popup display when we click the button.

The popup content is inside the q-popup-proxy ‘s default slot.

We can make the popup display when we right-click with the context-menu prop:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <div class="q-pa-md">
          <q-btn push color="primary" label="button">
            <q-popup-proxy context-menu>
              <q-banner>
                <template v-slot:avatar>
                  <q-icon name="signal_wifi_off" color="primary" />
                </template>
                You are offline
              </q-banner>
            </q-popup-proxy>
          </q-btn>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {}
      });
    </script>
  </body>
</html>

We can also make the popup trigger when we click on an icon that we have in the input with:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <div class="q-pa-md">
          <q-input filled v-model="input" mask="date" :rules="['date']">
            <template v-slot:append>
              <q-icon name="event" class="cursor-pointer">
                <q-popup-proxy :breakpoint="600">
                  <q-date v-model="input"></q-date>
                </q-popup-proxy>
              </q-icon>
            </template>
          </q-input>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          input: undefined
        }
      });
    </script>
  </body>
</html>

Pull to Refresh

We can add pull to refresh functionality with the q-pull-to-refresh component.

For instance, we can write:

<!DOCTYPE html>
<html>
  <head>
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.min.css"
      rel="stylesheet"
      type="text/css"
    />
  </head>
  <body class="body--dark">
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.12.13/dist/quasar.umd.min.js"></script>
    <div id="q-app">
      <q-layout
        view="lHh Lpr lFf"
        container
        style="height: 100vh;"
        class="shadow-2 rounded-borders"
      >
        <div class="q-pa-md">
          <div class="q-pa-md scroll" style="height: 300px;">
            <q-pull-to-refresh @refresh="refresh">
              <div v-for="n in num" :key="n" class="q-mb-sm">
                {{num - n}} - Lorem ipsum
              </div>
            </q-pull-to-refresh>
          </div>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          num: 50
        },
        methods: {
          refresh(done) {
            setTimeout(() => {
              this.num += 50;
              done();
            }, 1000);
          }
        }
      });
    </script>
  </body>
</html>

We have the items that we can pull to refresh inside tyhe q-pull-to-refresh component.

In the refresh handler, we call done when we’re done refreshing the content.

Conclusion

We can add popups and pull to refresh into our Vue app with Quasar.