Building a full web form using Vue and Web Awesome

Previously, we learned how to build dropdowns, radio button groups, buttons, and combo boxes. I figure the next step is to put it all together and build a full web form. In today’s demo, we are going to build a “feedback” form where someone provides their name, contact information, and what they think of you. It doesn’t actually send it anywhere, but it shows the result, and it is easy enough to add something to record the results.

The last time around, we created https://grand-block-gar.codepen.app using the data files in https://github.com/steinbring/data/tree/main/v1/locations/us_states_municipalities_zctas to let the user select a state (using a list of suggestions), select a municipality (using a list of suggestions that are based upon the selected state), and select a zip code / postal code (using a list of suggestions that are based upon the selected municipality). In that demo, state management and form data are handled in App.vue, and the options for states, municipalities, and zip codes/postal codes use computed properties. ComboBox is imported from ComboBox.vue, accepts the properties “label”, “placeholder”, “disabled”, “options”, and “modelValue”, emits a new value for “modelValue” when the value of the web awesome combobox changes, and it only creates <wa-combobox> inside the component.

So, what are we doing this time? In this week’s demo, we are doing the same thing (the Web Awesome components are in Vue child components and the data and computed properties are in parent components), except the form itself is in a child of App.vue.

The form asks for your name, your opinion, your contact information, and your preferred contact method. If you select that you want to be contacted by phone, it uses the radio group element to ask about when you would like to be called.

To use the form “in anger”, you would want to add an API call to an endpoint that could send an email and/or save the submission to a database record. Since the web component is added to the Vue component, and the form elements’ Vue components are as generic as possible, swapping out Web Awesome for something like Bootstrap or Bulma is pretty easy.

Example: https://optimal-brook-eft.codepen.app

#VueJs #WebAwesome #WebComponents

How to use wa-combobox with Vue

Previously, we used wa-dropdown to build a state, city, and zip dropdown set, and two years ago, we looked at implementing autocomplete with Vue. Today, we are going to look at how to use Web Awesome’s Combobox component to combine the two. This demo uses the same dataset that I used for the dropdown demos. It also obviously uses the same CodePen 2.0 style that we used previously.

As before, App.vue is the core of our application. There is a ComboBox.vue file that creates the ComboBox using the wa-combobox component. Feel free to fork the pen, experiment with the code, and see how easily you can adapt it for your own Vue projects. Happy coding!

Example: https://grand-block-gar.codepen.app

#Autocomplete #VueJs #WebAwesome #WebComponents

Trying to figure out the CodePen 2.0 editor

Recently, CodePen introduced CodePen 2.0, and since then, I have been trying to figure out how to modify my workflow for this blog to use it. I have been using CodePen to host my code demos for over six years now, and it feels weird to change, but it seems like a positive development. Lately, I have been writing a lot of posts about how to use Vue.js with Web Awesome. Let’s start with something that we can use to demonstrate basic functionality with Vue.js, Web Awesome, and Font Awesome.

So, what’s going on here? In previous demos (like the one for More Web Awesome Dropdowns), there were three files for each pen (the markup, CSS, and JavaScript). For 2.0 pens, you can have many more (and it uses Vite). In the demo above, App.vue handles the application layout, Header.vue handles the header, and CounterButton.vue handles the button’s behavior. I have done A LOT of experimentation since the 2.0 editor dropped, and I can’t get a few things (like Vue Router) to work, but I am hoping that will come with time. Since I can add more files, I added the social meta tags and a manifest.json. It means that the result should be more shareable on its own. I also added a light-mode/dark-mode toggle, a link to view the files, and a link to the blog post.

I think that, moving forward, I will keep using the same header. I hope that you appreciate the result.

Example: https://strange-scene-malamute.codepen.app

#CodePen #FontAwesome #VueJs #WebAwesome

More Web Awesome Dropdowns

Back in February, we looked at how to use Vue.js and Web Awesome to create dropdowns. I wanted to take a moment to look at other ways we can use Vue and Web Awesome to do cool things with Dropdowns. In today’s post, we will use the data files at data.jws.app to populate dropdowns in a webform. We previously used that data while looking at how to implement an autocomplete using web components. That work used Lit to create more maintainable Web Components that could be used and reused in development projects. Instead of using Lit this time, we are going to be using Web Awesome, but since Web Awesome uses Lit, we are still kind of using Lit. For today’s demos, we will look at how to create a contact form.

Our data website has a JSON file listing counties in Wisconsin. If we get that data asynchronously in onMounted(), we can populate a Ref with the listing of counties. At that point, you just need a v-for loop.

CodePen Embed Fallback

This has minimal utility because most contact forms will be used outside the great state of Wisconsin. I created a 426KB data file that has the names of the counties in every state. If we use a computed value for both the stateNames and countyNames arrays, we can make the list of county names depend on the selected state.

CodePen Embed Fallback

If the goal is to get the user’s contact information, you are more likely to want their state, city, and zip code rather than their state and county. The problem is that the data file balloons a lot at this point. A single data file containing every state, city, and zip code is 10.5 MB, which is a lot for a slower data connection to download. For the next example, we will try to use the same pattern as the last one.

CodePen Embed Fallback

As I said above, the problem is that our data file is ridiculously large. A 10.5 MB dependency on a webpage is unacceptable. My rule of thumb has always been that if a webpage can’t load over a bad cellular connection, it doesn’t function. If we want to have State, City, and Zip Code dropdowns, we can’t reduce the amount of data we are working with, but we can reduce the amount of data that is loaded into memory at the same time.

To make the final demo more performant, I split the data file into one for states and another for cities and ZIP codes in each state (e.g., AL, AK, AZ, AR). Now, the data file for the states is only 5.96 KB, and the data file for cities and zip codes in Wisconsin is 215 KB. 220.96 KB is much easier for mobile data users. Let’s see what that would look like.

CodePen Embed Fallback

We still watch the state, city, and zip values, but now we use await fetch() to retrieve the city and zip code data when the selected state changes.

What’s next? The inevitable next step would be to integrate street addresses, but if the dataset for US states, cities, and zip codes is 10.5 MB, the dataset for every street address in America would be significantly larger. The better option would be to use an API connected to a GIS server.

First Example: https://codepen.io/steinbring/pen/NPrjvNx/6f7d77a802b2fb359f3432ccf3844fe5

Second Example: https://codepen.io/steinbring/pen/wBWdVYW/fc70e2d022318800492654b73559cbe7

Third Example: https://codepen.io/steinbring/pen/xbOWqdN/ebbd160959669145be5a28f53f3f4e9e

Fourth Example: https://codepen.io/steinbring/pen/jErzBvK/cb69e49c7402268053845a0abd0f1f84

#VueJs #WebAwesome
The Fulcrum 10 April, 2026

Welcome to this week’s The Programmer’s Fulcrum.

It’s your weekly review of the essential news in the Open Media Network and Fediverse development communities with a focus on devastating big tech via Techno Anarchism. We aim to provide actionable content you can use to destroy Techno Feudalism each week. It has the additional benefit of weakening authoritarianism.

IMHO, the best way to do […]

https://newsletter.mobileatom.net/the-fulcrum-10-april-2026/ #ActivityPub #astro #ATProto #BackdropCMS #Bear #Bonfire #Codefloe #CSS #Decidim #DWeb #EmDash #FDroid #FediLab #fediverse #Ghost #Holos #HTML #HTMX #JavasScript #Kdenlive #LAUTI #Linux #OMN #PWAs #RSS #WebAwesome #WordPress #WriteFreely #XMPP #xWiki

How to use wa-radio-group with Vue

Previously, we went over how to use wa-card, wa-grid, wa-dropdown, and wa-relative-time. The next post in the Web Awesome/Vue series will be about the wa-radio-group component. This could be useful for wiring up a web form or for writing the interface for a results listing (like the “Buy Now,” “Make an Offer,” or “Auction” interface on eBay). Let’s see what is possible with Web Awesome.

For our first, let’s look at the simplest possible example. There is a horizontal radio button group, a vertical radio button group, colorOptions and foodOptions arrays to control what the radio button groups consist of, and ref objects for selectedColor and selectedFood.

CodePen Embed Fallback

If you add an appearance="button" attribute to the wa-radio blocks, it changes it from looking like a group of buttons instead of radio controls.

CodePen Embed Fallback

You will notice, though, that Vue variables for defining the options and what is selected are fine, but the value for what is selected doesn’t change when you change what is selected. So, how can you do that?

CodePen Embed Fallback

The only change in this final example is the addition of an @change="selectedColor = $event.target.value" attribute. Whenever the selection changes, it fires that and changes the value.

Please feel free to drop a comment if you have a question about any of this.

First example: https://codepen.io/steinbring/pen/WbxweXR/e045e86b81364eca311b9c0982b711c5

Second example: https://codepen.io/steinbring/pen/YPWqKpM/f47bd1b7334c432dc9ad5de93a281adc

Third example: https://codepen.io/steinbring/pen/dPXMWog/9d4c39becfdd948bd43eacc80cca0428

#VueJs #WebAwesome
Has anyone tried adding @fontawesome and @webawesome to a 2.0 pen on @codepen? In https://www.youtube.com/shorts/CO_9Zx9ELEc, @chriscoyier adds an import to script.js that references the NPM package for Web Awesome, and then #CodePen generates a package.json. I'm still trying to figure out how to do that with an NPM auth token.

#WebAwesome #FontAwesome #NPM

Has anyone figured this out?
Use Web Awesome Components in CodePen 2.0 Editor

YouTube

How to use wa-relative-time with Vue

Back when we looked at how to use wa-grid with Vue, we ended up with something that had the dates the individual photos were taken.

CodePen Embed Fallback

That is cool, but Web Awesome offers a second option. There is a wa-relative-time component that gives you the amount of time that has passed since that date. Let’s see what that would look like.

CodePen Embed Fallback

Would I use that in a finished product? I’m not too sure. It is always nice to have options, though.

Example: https://codepen.io/steinbring/pen/GgqpmJp/b7435756762bd672ed8865168de94943

#VueJs #WebAwesome

I like what I built post-2022

I wrote a few years ago about how I future-proofed my online identity by mirroring my writing in 2018 and then moved off of centralized social media in 2022. I now have my social media on JWS.Social instead of Twitter, I have my photos on Photos.JWS and JWS Pictures instead of Instagram, Flickr, and Tumblr, and I have been off of Reddit for years. This means that I don’t need to worry about the platform I am using being used to illegally generate deep-fake child porn, but it also means that I get to control what I can do with my own content. If I decide that I want GIFs.JWS to be available through an RSS feed, Mastodon, and BlueSky, I can do that. You don’t get the ability to do that with a platform like Facebook.

There are new concerns to consider after transitioning from legacy social media. On October 30, 2025, K&T Hosting announced it would cease operations and close by January 15, 2026. As a result, I had to migrate JWS.Social from K&T to Fedihost. Others host their instances on platforms like Akamai Cloud or DigitalOcean. Many users prefer services like Mastodon.Social or Hachyderm. All these options have their advantages and disadvantages. The good thing is that decentralized social media lets you do what you want and change your mind whenever you want.

Back in 2024, I moved JWS.Dev from using VuePress to using VitePress. I also created JWS.Pictures as an experiment to explore what you can do with GitHub Actions. I’m not terribly happy with either, but I do like the automations behind JWS.Pictures, and I like the look of JWS.Dev. I have been exploring Web Awesome and Vue.js here, and I am probably going to try to use both to rewrite the front-end of both websites.

#GoToSocial #VueJs #WebAwesome

How to use wa-dropdown with Vue

So far in our Web Awesome/Vue series, we have covered wa-card and wa-grid. Two years ago, I wrote about building a photography website (that admittedly had a shitty UI). The important part was the GitHub Actions that were triggered when a new photo was added. The script behind that creates versions of the photo file and appends that photo’s data to the JSON and XML files. Those data files let us fetch the years the photos were taken, the countries where the photos were taken, the years I took photos in each country, and the countries where I took photos for each year. In this post, we will look at how to create a Web Awesome dropdown menu, how to use those values to drive it, and ultimately, how to have both a “years” dropdown and a “countries” dropdown that affect each other.

Web Awesome’s wa-dropdown component is pretty easy to drive from a computed property. Let’s start by populating a dropdown with years from 2018 through the current year.

CodePen Embed Fallback

You don’t need a computed property to populate your dropdown element, though. You can also populate it from a normal array.

CodePen Embed Fallback

In this second example, we are using static values to populate a “Countries” dropdown. I want both a “Years” dropdown and a “Countries” dropdown in the finished project. Let’s see what that would look like next.

CodePen Embed Fallback

Like the first two examples, the third one also has the years as a computed property and the countries as a static array of strings.

If we are going to use this as a display filter for photos, I’m not a prolific enough traveler to have photos from every country every year, and we want to avoid a “no photos found” result, we will need to make one dropdown affect the other. If the user selects “Italy” and I was only in Italy in 2022, it wouldn’t make sense to allow the user to select 2023. In a similar vein, if the user selects 2024 and I was only in Japan, South Korea, and Taiwan in 2024, it wouldn’t make sense to allow them to select Italy.

So, what would that look like?

CodePen Embed Fallback

In this final example, once the user selects a year, the available countries are constrained; once a country is selected, the available years are constrained. There are refs for selectedYear and selectedCountry, enabling a future version where cards display the resulting photos.

First example: https://codepen.io/steinbring/pen/xbOGPBP/ac9a54f9138ab18b67f1dbe6857a0774

Second example: https://codepen.io/steinbring/pen/OPXVzLe/bc980fc7c7c361338016dced1eb78db4

Third example: https://codepen.io/steinbring/pen/emzNypR/91c65d642cd2cbce0fbe81a847ad6fc7

Fourth example: https://codepen.io/steinbring/pen/JoKdMRZ/4215aaa4233159d617233f1084e7c069

Fifth example: https://codepen.io/steinbring/pen/PwzqEpo/192ca335ef8aaff25ca960acf1ee3809

Sixth example: https://codepen.io/steinbring/pen/XJKbQBE/eb43f6c03098dc29b86ee6cfa5e4d890

Seventh example: https://codepen.io/steinbring/pen/XJKbQoY/7892f05989247885434ff3f7e74372f5

Eighth example: https://codepen.io/steinbring/pen/ByzoWWB/f935c8c6b6ad52e1d991a386b5b57a04

#VueJs #WebAwesome