npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

sdl-hello-vue

v1.0.1

Published

An Advanced Vue.js project w/custom elements

Downloads

2

Readme

Vaadin components with Vue.js

NOTE: This project will continue on the Vaadin with Vue Starter App. Please download the starter before reading this tutorial.

Instructions

We will use some extra Vaadin components and iron elements, to install them:

  yarn add @polymer/iron-pages
  yarn add @polymer/iron-form
  yarn add @vaadin/vaadin-core

Now we need to include all the dependencies. In src/App.vue add those imports right after the opening of the '` tag:

  import '@polymer/iron-pages';
  import '@polymer/iron-form';
  import '@vaadin/vaadin-core';

We will also make a slight change in the main app style, in the index.html, add this custom style in the <head> section:

  <custom-style>
    <style include="lumo-color lumo-typography">
      html {
        background-color: hsla(214, 57%, 24%, 0.1);
      }
    </style>
  </custom-style>

And a component specific style with few lumo theme variables, in src/App.vue, in the <style> section add:

  .card {
    width: 70%;
    margin: var(--lumo-space-m);
    padding: var(--lumo-space-m);
    border-radius: var(--lumo-border-radius);
    background-color: var(--lumo-base-color);
    box-shadow: var(--lumo-box-shadow-s);
  }

Let's also create some data types to be used by the application:

Create Address.js as following:

  import { Component } from 'react';

  class Address extends Component {
    constructor(props) {
      super(props);

      this.street = '';
      this.city = '';
      this.state = '';
      this.zip = '';
      this.country = '';
      this.phone = '';
    }
  }

  export default Address;

And create Person.js as:

  import { Component } from 'react';
  import Address from './Address';

  class Person extends Component {
    constructor(props) {
      super(props);

      this.firstName = '';
      this.LastName = '';
      this.address = new Address();
      this.email = '';
    }
  }

  export default Person;

Now inside App.vue we will construct the html responsible about rendering the app. Delete the content of <div id="app"> and replace it by:

A tabbed component to display two tabs:

  <vaadin-tabs :selected="selectedPage" v-on:selected-changed="selectedPage=$event.detail.value">
    <vaadin-tab>All Contacts</vaadin-tab>
    <vaadin-tab>Add New</vaadin-tab>
  </vaadin-tabs>

A component to render multiple pages for tabs:

  <iron-pages :selected="selectedPage">

  <div class="card">
  …
  </div>
  <div class="card">
  …
  </div>

  </iron-pages>

Here we note that the selected page is associated with the same variable as vaadin-tabs, so changing selectedPage value is enough to change the page. We have two div holding cards, those are going to be the two pages of our component as following:

A grid to hold the data:

  <vaadin-grid ref="grid" v-html="gridHtml" :items="users"></vaadin-grid>

Note the usage of v-html, which is a workaround that helps rendering <template> and should be defined in the data() section as:

  gridHtml: `
    <vaadin-grid-column width="60px" flex-grow="0">
      <template class="header">#</template>
      <template>{{index}}</template>
    </vaadin-grid-column>

    <vaadin-grid-column>
      <template class="header">
        <vaadin-grid-filter aria-label="First Name" path="firstName" value="{{_filterFirstName}}">
          <vaadin-text-field slot="filter" placeholder="First Name" value="{{_filterFirstName}}" focus-target></vaadin-text-field>
        </vaadin-grid-filter>
      </template>
      <template>{{item.firstName}}</template>
    </vaadin-grid-column>

    <vaadin-grid-column>
      <template class="header">
        <vaadin-grid-filter aria-label="Last Name" path="lastName" value="[[_filterLastName]]">
          <vaadin-text-field slot="filter" placeholder="Last Name" value="{{_filterLastName}}" focus-target></vaadin-text-field>
        </vaadin-grid-filter>
      </template>
      <template>{{item.lastName}}</template>
    </vaadin-grid-column>

    <vaadin-grid-column width="8em">
      <template class="header">Address</template>
      <template>
        <div style="white-space: normal">{{item.address.street}}, {{item.address.city}}</div>
      </template>
    </vaadin-grid-column>
  `,

Second card is a responsive form for data entry with validation:

  <iron-form ref="form">
    <form>
      <vaadin-form-layout>

        <vaadin-form-item>
          <label slot="label">First Name</label>
          <vaadin-text-field
            :value="newUser.firstName"
            @input="newUser.firstName=$event.target.value"
            required
            error-message="Please enter first name"
            class="full-width">
          </vaadin-text-field>
        </vaadin-form-item>

        <vaadin-form-item>
          <label slot="label">Last Name</label>
          <vaadin-text-field
            :value="newUser.lastName"
            @input="newUser.lastName=$event.target.value"
            required
            error-message="Please enter last name"
            class="full-width">
          </vaadin-text-field>
        </vaadin-form-item>

        <vaadin-form-item>
          <label slot="label">Birth date</label>
          <vaadin-date-picker class="full-width"></vaadin-date-picker>
        </vaadin-form-item>

        <vaadin-form-item>
          <label slot="label">Language</label>
          <vaadin-combo-box class="full-width" :items="langauges"></vaadin-combo-box>
        </vaadin-form-item>

        <vaadin-form-item colspan="2">
          <label slot="label">Notes</label>
          <vaadin-text-area class="full-width"></vaadin-text-area>
        </vaadin-form-item>

        <vaadin-form-item colspan="2">
          <vaadin-checkbox>I have read the <a href @click="toggleDialog">terms and conditions</a></vaadin-checkbox>
        </vaadin-form-item>

        <vaadin-form-item colspan="2">
          <vaadin-button @click="submitForm">Submit</vaadin-button>
        </vaadin-form-item>

      </vaadin-form-layout>
    </form>
  </iron-form>

We also place a notification components to notify the user about the status of the data entry:

  <vaadin-notification ref="formSubmitted" duration="4000" v-html="successNotificationHtml">
  </vaadin-notification>

  <vaadin-notification ref="formInvalid" duration="4000" v-html="errorNotificationHtml">
  </vaadin-notification>

And a dialog component to pop up when clicked on the terms and conditions link:

  <vaadin-dialog :opened="dialogOpen" v-html="dialogHtml">
  </vaadin-dialog>

Note the usage of v-html in the notifications and the dialog. The templates can be definied again in the data() section as:

  successNotificationHtml: `
    <template>
      A new contact has been added successfully.
    </template>
  `,
  errorNotificationHtml: `
    <template>
      Some fields are missing or invalid.
    </template>
  `,
  dialogHtml: `
    <template>
      <vaadin-vertical-layout theme="spacing">
        <div>
          <h1>The content of dialog</h1>
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin maximus magna et orci lacinia maximus. Fusce ut tincidunt ex. Morbi sed vehicula metus. Phasellus vel leo a elit viverra congue. Donec finibus iaculis eros vel vestibulum. Cras vehicula neque enim, eget faucibus ligula tempus vel. Integer felis nisi, sollicitudin at lectus at, bibendum vulputate risus. In ut massa et massa scelerisque viverra.</p>
        </div>
        <vaadin-button @click="toggleDialog">OK</vaadin-button>
      </vaadin-vertical-layout>
    </template>
  `,

Now to update the application logic:

First define few variables in the data() section, that we will use:

  users: JSON.stringify([]),
  selectedUsers: [],
  newUser: new Person(),

  langauges: JSON.stringify(['Dutch', 'English', 'French']),
  selectedPage: 0,
  dialogOpen: false,

We also need to fetch data from the server to be displayed in the grid, we can do that in the create life cycle by placing this:

  created() {
    fetch("https://demo.vaadin.com/demo-data/1.0/people?count=200")
      .then(res => res.json())
      .then(
        (result) => {
          this.users = JSON.stringify(result.result);
        },
        (error) => {
          // Handle Error
        }
      );
  },

Finally in the methods section, we define this method toggles the dialog when the link is clicked:

  toggleDialog() {
    this.dialogOpen = !this.dialogOpen;
  },

And this function will process the form submission. First make sure that it’s valid, if so then inserts the new item in the grid, select it, and switch back to the grid view with a success notification. Otherwise error notification is shown and validation errors are hilighted:

  submitForm(form) {
    if (this.$refs.form.validate()) {
      this.$refs.formSubmitted.open();

      let grid = this.$refs.grid;
      grid.items.unshift(this.newUser);
      grid.selectedItems = [];
      grid.selectItem(this.newUser);
      grid.clearCache();

      this.newUser = new Person();
      this.selectedPage = 0; // Go back
    } else {
      this.$refs.formInvalid.open();
    }
  }