Categories
Quasar

Developing Vue Apps with the Quasar Library — Responsive Images and Infinite Scroll

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.

Responsive Images

We can add responsive images with the srcset 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-img
            src="https://cdn.quasar.dev/img/image-src.png"
            srcset="https://cdn.quasar.dev/img/image-1x.png 300w,
                  https://cdn.quasar.dev/img/image-2x.png 2x,
                  https://cdn.quasar.dev/img/image-3x.png 3x,
                  https://cdn.quasar.dev/img/image-4x.png 4x"
            style="height: 280px; max-width: 300px;"
          >
          </q-img>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {}
      });
    </script>
  </body>
</html>

We set the srcset prop to a comma-separated list of image URLs.

Infinite Scroll

We can add an infinite scroll container with the q-infinite-scroll 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">
          <q-infinite-scroll @load="onLoad" :offset="250">
            <div v-for="(item, index) in items" :key="index" class="caption">
              <p>
                Lorem ipsum
              </p>
            </div>
            <template v-slot:loading>
              <div class="row justify-center q-my-md">
                <q-spinner-dots color="primary" size="40px" />
              </div>
            </template>
          </q-infinite-scroll>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          items: [{}, {}, {}, {}, {}, {}, {}]
        },
        methods: {
          onLoad(index, done) {
            setTimeout(() => {
              if (this.items) {
                this.items.push({}, {}, {}, {}, {}, {}, {});
                done();
              }
            }, 2000);
          }
        }
      });
    </script>
  </body>
</html>

We listen to the load event to run code to load more data when we scroll to the bottom of the container.

The offset has the distance above the bottom to trigger the loading.

We populate the loading slot to show the spinner when the items are loading.

We can change the scroll container with by setting the scroll-target 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">
          <div
            id="scroll-target-id"
            class="q-pa-md"
            style="max-height: 248px; overflow: auto;"
          >
            <q-infinite-scroll
              @load="onLoad"
              :offset="250"
              scroll-target="#scroll-target-id"
            >
              <div v-for="(item, index) in items" :key="index" class="caption">
                <p>
                  Lorem ipsum
                </p>
              </div>
              <template v-slot:loading>
                <div class="row justify-center q-my-md">
                  <q-spinner-dots color="primary" size="40px" />
                </div>
              </template>
            </q-infinite-scroll>
          </div>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          items: [{}, {}, {}, {}, {}, {}, {}]
        },
        methods: {
          onLoad(index, done) {
            setTimeout(() => {
              if (this.items) {
                this.items.push({}, {}, {}, {}, {}, {}, {});
                done();
              }
            }, 2000);
          }
        }
      });
    </script>
  </body>
</html>

We set it to the selector of the container we want to set as the scroll container.

Conclusion

We can add an infinite scroll container into our Vue app with Quasar.

Categories
Quasar

Developing Vue Apps with the Quasar Library — Image Styles, Transitions, and Errors

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.

Image Styles

We can change image styles with the style and img-class 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"  
      >  
        <div class="q-pa-md">  
          <q-img  
            src="https://cdn.quasar.dev/img/parallax2.jpg"  
            spinner-color="white"  
            style="height: 170px; max-width: 300px;"  
            img-class="my-custom-image"  
            class="rounded-borders"  
          >  
            <div class="absolute-bottom text-subtitle1 text-center">  
              Caption  
            </div>  
          </q-img>  
        </div>  
      </q-layout>  
    </div>  
    <script>  
      new Vue({  
        el: "#q-app",  
        data: {}  
      });  
    </script>  
  </body>  
</html>

We can add transition effects when loading images with the transition 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-img  
            transition="slide-right"  
            :src="url"  
            style="width: 150px;"  
            ratio="1"  
            spinner-color="white"  
            class="rounded-borders"  
          >  
          </q-img>  
        </div>  
      </q-layout>  
    </div>  
    <script>  
      new Vue({  
        el: "#q-app",  
        data: {  
          url: "https://placeimg.com/500/300/nature"  
        }  
      });  
    </script>  
  </body>  
</html>

We set the transition prop with the name of the transition to show when the image is loading.

Other possible values include:

  • ‘slide-left’
  • ‘slide-up’
  • ‘slide-down’
  • ‘fade’
  • ‘scale’
  • ‘rotate’
  • ‘flip-right’
  • ‘flip-left’
  • ‘flip-up’
  • ‘flip-down’
  • ‘jump-right’
  • ‘jump-left’
  • ‘jump-up’
  • ‘jump-down’

We can change the spinner by populating the loading slot:

<!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-img :src="url">  
            <template v-slot:loading>  
              <q-spinner-gears color="white"></q-spinner-gears>  
            </template>  
          </q-img>  
        </div>  
      </q-layout>  
    </div>  
    <script>  
      new Vue({  
        el: "#q-app",  
        data: {  
          url: "https://placeimg.com/500/300/nature"  
        }  
      });  
    </script>  
  </body>  
</html>

We can also add a placeholder image by setting the placeholder-src slot to an image URL:

<!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-img  
            :src="url"  
            placeholder-src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAACWBAMAAADOL2zRAAAAG1BMVEXMzMyWlpaqqqq3t7fFxcW+vr6xsbGjo6OcnJyLKnDGAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABAElEQVRoge3SMW+DMBiE4YsxJqMJtHOTITPeOsLQnaodGImEUMZEkZhRUqn92f0MaTubtfeMh/QGHANEREREREREREREtIJJ0xbH299kp8l8FaGtLdTQ19HjofxZlJ0m1+eBKZcikd9PWtXC5DoDotRO04B9YOvFIXmXLy2jEbiqE6Df7DTleA5socLqvEFVxtJyrpZFWz/pHM2CVte0lS8g2eDe6prOyqPglhzROL+Xye4tmT4WvRcQ2/m81p+/rdguOi8Hc5L/8Qk4vhZzy08DduGt9eVQyP2qoTM1zi0/uf4hvBWf5c77e69Gf798y08L7j0RERERERERERH9P99ZpSVRivB/rgAAAABJRU5ErkJggg=="  
          >  
          </q-img>  
        </div>  
      </q-layout>  
    </div>  
    <script>  
      new Vue({  
        el: "#q-app",  
        data: {  
          url: "https://placeimg.com/500/300/nature"  
        }  
      });  
    </script>  
  </body>  
</html>

We can add an image that’s displayed when the image we point to doesn’t load by populating the error slot:

<!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-img :src="url" style="height: 140px; max-width: 150px;">  
            <template v-slot:error>  
              <div  
                class="absolute-full flex flex-center bg-negative text-white"  
              >  
                Cannot load image  
              </div>  
            </template>  
          </q-img>  
        </div>  
      </q-layout>  
    </div>  
    <script>  
      new Vue({  
        el: "#q-app",  
        data: {  
          url: "abc"  
        }  
      });  
    </script>  
  </body>  
</html>

Conclusion

We can set image styles, add placeholders, spinners, and error images with Quasar.

Categories
Quasar

Developing Vue Apps with the Quasar Library — Icons and Images

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.

Icons

We can add icons with the q-icon 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">
          <q-icon
            name="print"
            class="text-teal"
            style="font-size: 4.4em;"
          ></q-icon>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {}
      });
    </script>
  </body>
</html>

We add the q-icon component with the name to set the icon to display.

And we change the class and style attributes to change the styles.

We can set the size with the size 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-icon name="print" size="xl"></q-icon>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {}
      });
    </script>
  </body>
</html>

Other options include ‘xs’, ‘sm’, ‘md’, and ‘lg’ .

Images

We can add images with the q-img 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">
          <q-btn
            push
            color="teal"
            label="Change image"
            @click="refresh"
          ></q-btn>
          <q-img
            :src="url"
            spinner-color="white"
            style="height: 140px; max-width: 150px;"
          >
          </q-img>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          url: "https://placeimg.com/500/300/nature"
        },
        methods: {
          refresh() {
            this.url = `https://placeimg.com/500/300/nature?t=${Math.random()}`;
          }
        }
      });
    </script>
  </body>
</html>

We set the src prop to set the URL of the image.

spinner-color changes the spinner color.

When we change the URL by calling refresh , the spinner will show.

We can change the aspect ratio with the ratio 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-img :ratio="16/9" :src="url" spinner-color="white"> </q-img>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          url: "https://placeimg.com/500/300/nature"
        }
      });
    </script>
  </body>
</html>

We can add captions into the default slot:

<!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-img :ratio="16/9" :src="url" spinner-color="white">
            <div class="absolute-bottom text-subtitle1 text-center">
              Caption
            </div>
          </q-img>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          url: "https://placeimg.com/500/300/nature"
        }
      });
    </script>
  </body>
</html>

Conclusion

We can add icons and images into our Vue app with Quasar.

Categories
Quasar

Developing Vue Apps with the Quasar Library — Date Picker and Inputs

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.

Date Picker in Inputs

We can add date pickers inside inputs.

To do this, we add the date picker into the append slot:

<!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="date" mask="date" :rules="['date']">
            <template v-slot:append>
              <q-icon name="event" class="cursor-pointer">
                <q-popup-proxy
                  ref="qDateProxy"
                  transition-show="scale"
                  transition-hide="scale"
                >
                  <q-date v-model="date">
                    <div class="row items-center justify-end">
                      <q-btn v-close-popup label="Close" color="primary" flat />
                    </div>
                  </q-date>
                </q-popup-proxy>
              </q-icon>
            </template>
          </q-input>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          date: "2020/12/01"
        }
      });
    </script>
  </body>
</html>

We add the q-icon with the q-popup-proxy to add the popup.

Then we add the q-date component inside it so that it opens when we click the icon.

Also, we can add the date and time picker together in an input:

<!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="date">
            <template v-slot:prepend>
              <q-icon name="event" class="cursor-pointer">
                <q-popup-proxy transition-show="scale" transition-hide="scale">
                  <q-date v-model="date" mask="YYYY-MM-DD HH:mm">
                    <div class="row items-center justify-end">
                      <q-btn v-close-popup label="Close" color="primary" flat />
                    </div>
                  </q-date>
                </q-popup-proxy>
              </q-icon>
            </template>

            <template v-slot:append>
              <q-icon name="access_time" class="cursor-pointer">
                <q-popup-proxy transition-show="scale" transition-hide="scale">
                  <q-time v-model="date" mask="YYYY-MM-DD HH:mm" format24h>
                    <div class="row items-center justify-end">
                      <q-btn v-close-popup label="Close" color="primary" flat />
                    </div>
                  </q-time>
                </q-popup-proxy>
              </q-icon>
            </template>
          </q-input>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          date: "2020/12/01"
        }
      });
    </script>
  </body>
</html>

We add the date picker on the left side by populating the prepend slot.

And we add the time picker into the append slot.

Native Submit

We can get the data from the form in the evt.target property:

<!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-form [@submit](https://medium.com/r/?url=http%3A%2F%2Ftwitter.com%2Fsubmit "Twitter profile for @submit")="onSubmit" class="q-gutter-md">
            <q-date name="wedding" v-model="date"></q-date>

<div>
              <q-btn label="Submit" type="submit" color="primary"></q-btn>
            </div>
          </q-form>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          date: "2020/12/01"
        },
        methods: {
          onSubmit(evt) {
            const formData = new FormData(evt.target);
            const submitResult = [];
            for (const [name, value] of formData.entries()) {
              submitResult.push({
                name,
                value
              });
            }
            console.log(submitResult);
          }
        }
      });
    </script>
  </body>
</html>

We pass it into the FormData to create the form data object from it.

Conclusion

We can add date pickers into our Vue app with various options with Quasar.

Categories
Quasar

Developing Vue Apps with the Quasar Library — Date Picker Selections and Events

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.

Limit Date Picker Dates

We can limit the date picker dates that we can select in the calendar.

To do this, we add the options prop with an array of dates:

<!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-date :options="options" v-model="date"> </q-date>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          date: undefined,
          options: [
            "2020/12/01",
            "2020/12/05",
            "2020/12/06",
            "2020/12/09",
            "2020/12/23"
          ]
        }
      });
    </script>
  </body>
</html>

We can also limit the dates we can select with a method:

<!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-date :options="optionsFn" v-model="date"> </q-date>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          date: undefined
        },
        methods: {
          optionsFn(date) {
            return date >= "2020/12/03" && date <= "2020/12/15";
          }
        }
      });
    </script>
  </body>
</html>

We can compare the date parameter directly with a date string and return the condition for the date that we want to select.

We can also split the date string and check against that in the condition:

<!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-date :options="optionsFn" v-model="date"> </q-date>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          date: undefined
        },
        methods: {
          optionsFn(date) {
            const [year, month, day] = date.split("/");
            return day % 2 === 0;
          }
        }
      });
    </script>
  </body>
</html>

When the function returns true , the date can be selected.

Display the Content of Events

We can display the content of events with the q-splitter 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">
          <q-splitter v-model="splitterModel" style="height: 450px;">
            <template v-slot:before>
              <div class="q-pa-md">
                <q-date v-model="date" :events="events" event-color="orange" />
              </div>
            </template>

            <template v-slot:after>
              <q-tab-panels
                v-model="date"
                animated
                transition-prev="jump-up"
                transition-next="jump-up"
              >
                <q-tab-panel name="2020/12/01">
                  <div class="text-h4 q-mb-md">2020/12/01</div>
                  <p>
                    Lorem ipsum dolor sit
                  </p>
                  <p>
                    Lorem ipsum dolor sit
                  </p>
                </q-tab-panel>

                <q-tab-panel name="2020/12/05">
                  <div class="text-h4 q-mb-md">2020/12/05</div>
                  <p>
                    Lorem ipsum dolor sit
                  </p>
                  <p>
                    Lorem ipsum dolor sit
                  </p>
                </q-tab-panel>

                <q-tab-panel name="2020/12/06">
                  <div class="text-h4 q-mb-md">2020/12/06</div>
                  <p>
                    Lorem ipsum dolor sit
                  </p>
                  <p>
                    Lorem ipsum dolor sit
                  </p>
                  <p>
                    Lorem ipsum dolor sit
                  </p>
                </q-tab-panel>
              </q-tab-panels>
            </template>
          </q-splitter>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          date: "2020/12/01",
          splitterModel: 50,
          events: ["2020/12/01", "2020/12/05", "2020/12/06"]
        }
      });
    </script>
  </body>
</html>

We use v-model to bind the selected date to the date model.

events has the event dates.

We put the date picker on the left side with the before slot.

The after slot has the content we display on the right side.

We use the q-tab-panels to display content according to the date value.

If the date matches the name prop’s value on q-tab-panel , then it’ll be displayed.

Conclusion

We can display events and limit date selections with Quasar’s date picker.