Categories
Quasar

Developing Vue Apps with the Quasar Library — Parallax Scroll Speed and Popup Edit

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.

Parallax Scroll Speed

We can change the parallax scroll speed with the speed 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
            class="row justify-between overflow-scroll"
            style="height: 150px;"
          >
            <q-parallax :height="300" :speed="0.5">
              <template v-slot:media>
                <img src="https://cdn.quasar.dev/img/parallax1.jpg" />
              </template>

               <h1 class="text-white">Docks</h1>
            </q-parallax>
          </div>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          current: 1
        }
      });
    </script>
  </body>
</html>

We can get data about the scroll progress by getting the scope object from the content 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">
          <div
            class="row justify-between overflow-scroll"
            style="height: 150px;"
          >
            <q-parallax :height="500" :speed="0.5">
              <template v-slot:media>
                <img src="https://cdn.quasar.dev/img/parallax1.jpg" />
              </template>

              <template v-slot:content="scope">
                <div
                  class="absolute column items-center"
                  :style="{
                      opacity: 0.45 + (1 - scope.percentScrolled) * 0.55,
                      top: (scope.percentScrolled * 60) + '%',
                      left: 0,
                      right: 0
                    }"
                >
                  <img
                    src="https://cdn.quasar.dev/logo/svg/quasar-logo.svg"
                    style="width: 150px; height: 150px;"
                  />
                  <div class="text-h6 text-grey-3 text-center">
                    v{{ $q.version }}
                  </div>
                </div>
              </template>
            </q-parallax>
          </div>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          current: 1
        }
      });
    </script>
  </body>
</html>

We add the scroll content in the content slot and get the scroll progress with the scope.percentScrolled property.

Popup Edit

We can add the ability for the user to edit table cell data with the q-popup-edit 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-table
            :data="data"
            :columns="columns"
            title="QDataTable with QPopupEdit"
            :rows-per-page-options="[]"
            row-key="name"
          >
            <template v-slot:body="props">
              <q-tr :props="props">
                <q-td key="desc" :props="props">
                  {{ props.row.name }}
                  <q-popup-edit v-model="props.row.name" title="Edit the Name">
                    <q-input
                      v-model="props.row.name"
                      dense
                      autofocus
                      counter
                    ></q-input>
                  </q-popup-edit>
                </q-td>
                <q-td key="calories" :props="props">
                  {{ props.row.calories }}
                  <q-popup-edit v-model.number="props.row.calories">
                    <q-input
                      type="number"
                      v-model.number="props.row.calories"
                      dense
                      autofocus
                    >
                    </q-input>
                  </q-popup-edit>
                </q-td>
                <q-td key="fat" :props="props">
                  {{ props.row.fat }}
                  <q-popup-edit v-model.number="props.row.fat">
                    <q-input
                      type="number"
                      v-model.number="props.row.fat"
                      dense
                      autofocus
                    >
                    </q-input>
                  </q-popup-edit>
                </q-td>
                <q-td key="carbs" :props="props">
                  {{ props.row.carbs }}
                  <q-popup-edit v-model.number="props.row.carbs" disable>
                    <q-input
                      type="number"
                      v-model.number="props.row.carbs"
                      dense
                      autofocus
                    >
                    </q-input>
                  </q-popup-edit>
                </q-td>
                <q-td key="protein" :props="props">
                  {{ props.row.protein }}
                  <q-popup-edit v-model.number="props.row.protein">
                    <q-input
                      type="number"
                      v-model.number="props.row.protein"
                      dense
                      autofocus
                    >
                    </q-input>
                  </q-popup-edit>
                </q-td>
                <q-td key="sodium" :props="props">
                  {{ props.row.sodium }}
                  <q-popup-edit v-model.number="props.row.sodium">
                    <q-input
                      type="number"
                      v-model.number="props.row.sodium"
                      dense
                      autofocus
                    >
                    </q-input>
                  </q-popup-edit>
                </q-td>
                <q-td key="calcium" :props="props">
                  {{ props.row.calcium }}
                  <q-popup-edit v-model="props.row.calcium">
                    <template v-slot:title>
                      <div class="text-italic text-primary">
                        My Custom Title
                      </div>
                    </template>
                    <q-input v-model="props.row.calcium" dense autofocus />
                  </q-popup-edit>
                </q-td>
                <q-td key="iron" :props="props">
                  {{ props.row.iron }}
                  <q-popup-edit v-model="props.row.iron">
                    <q-input v-model="props.row.iron" dense autofocus />
                  </q-popup-edit>
                </q-td>
              </q-tr>
            </template>
          </q-table>
        </div>
      </q-layout>
    </div>
    <script>
      const columns = [
        {
          name: "desc",
          align: "left",
          label: "Dessert (100g serving)",
          field: "name"
        },
        {
          name: "calories",
          align: "center",
          label: "Calories",
          field: "calories"
        },
        { name: "fat", label: "Fat (g)", field: "fat" },
        { name: "carbs", label: "Carbs (g)", field: "carbs" }
      ];

      const data = [
        {
          name: "Frozen Yogurt",
          calories: 159,
          fat: 6.0,
          carbs: 24,
          protein: 4.0
        },
        {
          name: "Ice cream sandwich",
          calories: 237,
          fat: 9.0,
          carbs: 37,
          protein: 4.3
        },
        {
          name: "Eclair",
          calories: 262,
          fat: 16.0,
          carbs: 23,
          protein: 6.0
        }
      ];

      new Vue({
        el: "#q-app",
        data: {
          data,
          columns
        }
      });
    </script>
  </body>
</html>

We add the q-popup-edit component within the q-td component.

And we get the table cell data from the props.row property.

Conclusion

We can set the speed of parallax scrolling and add a popup edit box for table cells into our Vue app with Quasar.

Categories
Quasar

Developing Vue Apps with the Quasar Library — Paginator and Parallax 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.

Remove Ellipses from Paginator

We can set the ellipses prop to false to remove the ellipses from the paginator.

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-pagination
            :max="10"
            :max-pages="6"
            :boundary-numbers="false"
            :ellipses="false"
            v-model="current"
          >
          </q-pagination>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          current: 1
        }
      });
    </script>
  </body>
</html>

Boundary Links

We can add boundary links with the boundary-links 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-pagination
            :max="10"
            :max-pages="6"
            boundary-links
            v-model="current"
          >
          </q-pagination>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          current: 1
        }
      });
    </script>
  </body>
</html>

Direction Links

And we can add the direction links with the direction-links 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-pagination
            :max="10"
            :max-pages="6"
            direction-links
            v-model="current"
          >
          </q-pagination>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          current: 1
        }
      });
    </script>
  </body>
</html>

Parallax Scrolling

We can add parallax scrolling with the q-parallax component.

To use it, we 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="row justify-between">
            <q-parallax src="https://cdn.quasar.dev/img/parallax2.jpg">
              <h1 class="text-white">Basic</h1>
            </q-parallax>
          </div>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          current: 1
        }
      });
    </script>
  </body>
</html>

We just add the text content inside it.

And we set the src prop to the background image’s URL.

We can add a video as the background by populating the media slot with the video element:

<!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="row justify-between">
            <q-parallax>
              <template v-slot:media>
                <video
                  width="720"
                  height="440"
                  poster="https://cdn.quasar.dev/img/polina.jpg"
                  autoplay
                  loop
                  muted
                >
                  <source
                    type="video/webm"
                    src="https://cdn.quasar.dev/img/polina.webm"
                  />
                  <source
                    type="video/mp4"
                    src="https://cdn.quasar.dev/img/polina.mp4"
                  />
                </video>
              </template>

              <h1 class="text-white">Basic</h1>
            </q-parallax>
          </div>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          current: 1
        }
      });
    </script>
  </body>
</html>

Conclusion

We can add a paginator with various options and add parallax scroll with Quasar.

Categories
Quasar

Developing Vue Apps with the Quasar Library — Paginator

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.

Paginator

We can add the paginator component into our Vue app with Quasar’s q-pagination 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-pagination v-model="current" :max="5"> </q-pagination>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          current: 1
        }
      });
    </script>
  </body>
</html>

We bind the selected page number with v-model to the current reactive property.

max has the max number of page buttons to display.

We can ad icons with various icon 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-pagination
            :direction-links="true"
            :boundary-links="true"
            icon-first="skip_previous"
            icon-last="skip_next"
            icon-prev="fast_rewind"
            icon-next="fast_forward"
            v-model="current"
            :max="5"
          >
          </q-pagination>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          current: 1
        }
      });
    </script>
  </body>
</html>

We can change the page buttons to an input with the input 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-pagination input v-model="current" :max="5"> </q-pagination>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          current: 1
        }
      });
    </script>
  </body>
</html>

We can change the input color with the input-class :

<!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-pagination
            input
            input-class="text-orange-10"
            v-model="current"
            :max="5"
          >
          </q-pagination>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          current: 1
        }
      });
    </script>
  </body>
</html>

We can set the max number of page numbers to show with the max-pages 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-pagination
            :max="10"
            :max-pages="6"
            :boundary-numbers="false"
            v-model="current"
          >
          </q-pagination>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          current: 1
        }
      });
    </script>
  </body>
</html>

boundary-numbers set to false means we don’t always show the start or end page numbers.

Conclusion

We can add a paginator component into our Vue app with Quasar’s q-pagination component.

Categories
Quasar

Developing Vue Apps with the Quasar Library — Scroll Observer

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.

Scroll Observer

We can watch the scroll position of the scroll container with the q-scroll-observer 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="scroll overflow-scroll" style="height: 100px;">
            <div v-for="n in 100">lorem ipsum</div>
            <q-scroll-observer @scroll="onScroll"></q-scroll-observer>
          </div>

           <div>{{scrollInfo}}</div>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          scrollInfo: {}
        },
        methods: {
          onScroll(info) {
            this.scrollInfo = info;
          }
        }
      });
    </script>
  </body>
</html>

We add the q-scroll-observer component and listen to the scroll event with it.

Then we get the info from the onScroll event handler.

The info parameter is something like:

{ "position": 1100, "direction": "down", "directionChanged": false, "inflexionPosition": 0 }

position has the scroll position in pixels.

direction has the scroll direction.

directionChanged tells us whether the scroll direction has changed.

inflexionPosition is the last scroll position where the user changed the scroll position.

We can also add the v-scroll position to watch the scroll position:

<!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="scroll overflow-scroll" style="height: 100px;">
            <div v-for="n in 100">lorem ipsum</div>
            <div v-scroll="onScroll"></div>
          </div>

          <div>{{scrollInfo}}</div>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          scrollInfo: {}
        },
        methods: {
          onScroll(info) {
            this.scrollInfo = info;
          }
        }
      });
    </script>
  </body>
</html>

We get the scroll position with the info parameter.

The q-scroll-observer also works inside the q-scroll-area 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"
      >
        <div class="q-pa-md">
          <q-scroll-area style="height: 100px;" class="bg-yellow">
            <div v-for="n in 100">lorem ipsum</div>
            <q-scroll-observer @scroll="onScroll"></q-scroll-observer>
          </q-scroll-area>

          <div>{{scrollInfo}}</div>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          scrollInfo: {}
        },
        methods: {
          onScroll(info) {
            this.scrollInfo = info;
          }
        }
      });
    </script>
  </body>
</html>

We can also watch horizontal scrolling with the horizontal 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
            class="scroll overflow-scroll"
            style="width: 90vw; height: 100px;"
          >
            <span v-for="n in 1000">{{n}}</span>
            <q-scroll-observer
              horizontal
              @scroll="onScroll"
            ></q-scroll-observer>
          </div>

          <div>{{scrollInfo}}</div>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          scrollInfo: {}
        },
        methods: {
          onScroll(info) {
            this.scrollInfo = info;
          }
        }
      });
    </script>
  </body>
</html>

Conclusion

We can add the Quasar’s q-scroll-observer component to watch the scroll position in our Vue app.

Categories
Quasar

Developing Vue Apps with the Quasar Library — Menu Target Element and Observing Resize

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.

Menu Target Element

We can change the menu’s target element with q-menu ‘s 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 class="row justify-center">
            <div class="row items-center q-gutter-x-sm">
              <q-radio
                v-model="targetEl"
                :val="false"
                label="false (no target)"
              >
              </q-radio>
              <q-radio
                v-model="targetEl"
                :val="true"
                label="true (original parent)"
              >
              </q-radio>
              <q-radio
                v-model="targetEl"
                val="#target-img-1"
                label="#target-img-1"
              >
              </q-radio>
            </div>
          </div>
          <div class="row justify-center">
            <q-img
              src="https://cdn.quasar.dev/img/material.png"
              id="target-img-1"
              style="height: 100px;"
            >
              <div
                class="absolute-bottom-right"
                style="border-top-left-radius: 5px;"
              >
                #target-img-1
              </div>
            </q-img>
            <q-img
              src="https://cdn.quasar.dev/img/parallax2.jpg"
              id="target-img-2"
              style="height: 100px;"
            >
              <div
                class="absolute-bottom-right"
                style="border-top-left-radius: 5px;"
              >
                #target-img-2
              </div>
            </q-img>
            <q-img
              src="https://cdn.quasar.dev/img/blueish.jpg"
              style="height: 100px;"
            >
              <div
                class="absolute-bottom-right"
                style="border-top-left-radius: 5px;"
              >
                Original parent
              </div>
              <q-menu touch-position :target="targetEl">
                <q-list>
                  <q-item v-for="n in 5" :key="n" v-close-popup clickable>
                    <q-item-section>Label</q-item-section>
                  </q-item>
                </q-list>
              </q-menu>
            </q-img>
          </div>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          targetEl: "#target-img-1"
        }
      });
    </script>
  </body>
</html>

We set the targetEl reactive property to the selector for the image we want to target.

Also, we can set it to false to disable the menu for all elements.

Or we can set the target to true to set the target element to the original one set in data .

Resize Observer

We can watch the size of an element with the q-resize-observer component.

For example, we can use it by writing:

<!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
            style="width: 80vw; height: 50vh;"
            class="container bg-amber rounded-borders glossy"
          >
            <q-resize-observer @resize="onResize"></q-resize-observer>
          </div>

          <div class="q-gutter-sm">
            Reported:
            <q-badge>width: {{ report.width }}</q-badge>
            <q-badge>height: {{ report.height }}</q-badge>
          </div>
        </div>
      </q-layout>
    </div>
    <script>
      new Vue({
        el: "#q-app",
        data: {
          report: {}
        },
        methods: {
          onResize(size) {
            this.report = size;
          }
        }
      });
    </script>
  </body>
</html>

We add the q-resize-observer inside the element that we want to watch the size to watch its size when resizing.

We listen to the resize event to get the size.

The size parameter of the event handler has the width and height property to get the size.

Conclusion

We can set the target element for our menu and watch element size in our Vue app with Quasar.