Tag: Nuxt

Setting up and Customizing the Ant Design System in a Nuxt App

I don’t typically work with UI libraries because they can be cumbersome and hard to override, which can contribute to a bloated. However, Ant Design has recently gained some some of my affection because it’s easy to use, has extensible defaults, and features a delicate design.

Nuxt and Ant Design work well together, in part because of Nuxt’s code-splitting and tree-shaking abilities, not to mention Nuxt’s new static target deployment option. I can serve an app using Ant Design with great performance scores.

Combining the two was a little tricky and there isn’t a lot in the way of documentation for how to do it, so what follows are the steps you need to set it up. Let’s get started!

Install Ant.design 

The first step is installing the ant-design-vue package, along with Less.js and less-loader, which we will need to create our Less variables:

yarn add ant-design-vue less less-loader # or npm i ant-design-vue less less-loader

Now lets tell Nuxt to use it globally via a plugin. We’ll create a file called antd-ui.js:

import Vue from 'vue' import Antd from 'ant-design-vue/lib'  Vue.use(Antd)

You may notice that unlike the process outlined in the Ant Design getting started guide, we are not importing the global CSS file they mention. That’s because we’re going to manually import the base variable Less file instead so that we can override it. 

We have a few things to do in our nuxt.config.js file. First, let’s register the plugin we just made:

plugins: ["@/plugins/antd-ui"],

Next, we’re going to let webpack know we’d like to build Less:

build: {    loaders: {      less: {        lessOptions: {          javascriptEnabled: true,        },     },   }, }

Finally, we need to create a global stylesheet for our variables that imports Ant Design’s defaults as well as our overrides:

css: [   "~/assets/variables.less" ],

We can see that this file exists in a /assets folder, so let’s make it. We’ll create a file in there called variables.less, and import Ant Design’s Less variables:

@import '~ant-design-vue/dist/antd.less';

Below this line, there are myriad variables you can override. This is just a sampling. The rest of the variables are here, and you’ll need to include them by their @ and can change it to whatever you wish:

@primary-color: #1890ff; // primary color for all components @link-color: #1890ff; // link color @success-color: #52c41a; // success state color @warning-color: #faad14; // warning state color @error-color: #f5222d; // error state color @font-size-base: 14px; // major text font size @heading-color: rgba(0, 0, 0, 0.85); // heading text color @text-color: rgba(0, 0, 0, 0.65); // major text color @text-color-secondary: rgba(0, 0, 0, 0.45); // secondary text color @disabled-color: rgba(0, 0, 0, 0.25); // disable state color @border-radius-base: 4px; // major border radius @border-color-base: #d9d9d9; // major border color @box-shadow-base: 0 2px 8px rgba(0, 0, 0, 0.15); // major shadow for layers

We’re good to go! There’s no need to import what we need into every component because Nuxt will now take care of that. If you’d like to override very specific styles not included in the variables, you can find the associative classes and override them in your layouts/default.vue file as well.

Ant.design and Nuxt allow you a great framework for building apps very quickly and with ease. Enjoy!


The post Setting up and Customizing the Ant Design System in a Nuxt App appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , ,

Creating Dynamic Routes in a Nuxt Application

In this post, we’ll be using an ecommerce store demo I built and deployed to Netlify to show how we can make dynamic routes for incoming data. It’s a fairly common use-case: you get data from an API, and you either don’t know exactly what that data might be, there’s a lot of it, or it might change. Luckily for us, Nuxt makes the process of creating dynamic routing very seamless.

In the last post, we showed how to set up stripe payments with Netlify Functions, which allow us to create serverless lambda functions with ease. We’ll use this same application to show another Nuxt-specific functionality as well.

Let’s get started!

Creating the page

In this case, we’ve got some dummy data for the store that I created in mockaroo and am storing in the static folder. Typically you’ll use fetch or axios and an action in the Vuex store to gather that data. Either way, we store the data with Vuex in store/index.js, along with the UI state, and an empty array for the cart.

import data from '~/static/storedata.json'  export const state = () => ({  cartUIStatus: 'idle',  storedata: data,  cart: [] })

It’s important to mention that in Nuxt, all we have to do to set up routing in the application is create a .vue file in the pages directory. So we have an index.vue page for our homepage, a cart.vue page for our cart, and so on. Nuxt automagically generates all the routing for these pages for us.

In order to create dynamic routing, we will make a directory to house those pages. In this case, I made a directory called /products, since that’s what the routes will be, a view of each individual product details.

In that directory, I’ll create a page with an underscore, and the unique indicator I want to use per page to create the routes. If we look at the data I have in my cart, it looks like this:

[  {    "id": "9d436e98-1dc9-4f21-9587-76d4c0255e33",    "color": "Goldenrod",    "description": "Mauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero.",    "gender": "Male",    "name": "Desi Ada",    "review": "productize virtual markets",    "starrating": 3,    "price": 50.40,    "img": "1.jpg"  },   … ]

You can see that the ID for each entry is unique, so that’s a good candidate for something to use, we’ll call the page:

_id.vue

Now, we can store the id of the particular page in our data by using the route params:

data() {  return {    id: this.$  route.params.id,   } },

For the entry from above, our data if we looked in devtools would be:

id: "9d436e98-1dc9-4f21-9587-76d4c0255e33"

We can now use this to retrieve all of the other information for this entry from the store. I’ll use mapState:

import { mapState } from "vuex";  computed: {  ...mapState(["storedata"]),  product() {    return this.storedata.find(el => el.id === this.id);  } },

And we’re filtering the storedata to find the entry with our unique ID!

Let the Nuxt config know

If we were building an app using yarn build, we’d be done, but we’re using Nuxt to create a static site. When we use Nuxt to create a static site, we’ll use the yarn generate command. We have to let Nuxt know about the dynamic files with the generate command in nuxt.config.js.

This command will expect a function that will return a promise that resolves in an array that will look like this:

export default {   generate: {     routes: [       '/product/1',       '/product/2',       '/product/3'     ]   } }

To create this, at the top of the file we’ll bring in the data from the static directory, and create the function:

import data from './static/storedata.json' let dynamicRoutes = () => {  return new Promise(resolve => {    resolve(data.map(el => `product/$  {el.id}`))  }) }

We’ll then call the function within our config:

generate: {   routes: dynamicRoutes },

If you’re gathering your data from an API with axios instead (which is more common), it would look more like this:

import axios from 'axios' let dynamicRoutes = () => {  return axios.get('https://your-api-here/products').then(res => {    return res.data.map(product => `/product/$  {product.id}`)  }) }

And with that, we’re completely done with the dynamic routing! If you shut down and restart the server, you’ll see the dynamic routes per product in action!

For the last bit of this post, we’ll keep going, showing how the rest of the page was made and how we’re adding items to our cart, since that might be something you want to learn, too.

Populate the page

Now we can populate the page with whatever information we want to show, with whatever formatting we would like, as we have access to it all with the product computed property:

<main>  <section class="img">    <img :src="`/products/$  {product.img}`" />  </section>  <section class="product-info">    <h1>{{ product.name }}</h1>    <h4 class="price">{{ product.price | dollar }}</h4>    <p>{{ product.description }}</p>  </section>  ... </main>

In our case, we’ll also want to add items to the cart that’s in the store. We’ll add the ability to add and remove items (while not letting the decrease count dip below zero

<p class="quantity">  <button class="update-num" @click="quantity > 0 ? quantity-- : quantity = 0">-</button>  <input type="number" v-model="quantity" />  <button class="update-num" @click="quantity++">+</button> </p> ... <button class="button purchase" @click="cartAdd">Add to Cart</button>

In our methods on that component, we’ll add the item plus a new field, the quantity, to an array that we’ll pass as the payload to mutation in the store.

methods: {  cartAdd() {    let item = this.product;    item.quantity = this.quantity;    this.tempcart.push(item);    this.$  store.commit("addToCart", item);  } }

In the Vuex store, we’ll check if the item already exists. If it does, we’ll just increase the quantity. If not, we’ll add the whole item with quantity to the cart array.

addToCart: (state, payload) => {  let itemfound = false  state.cart.forEach(el => {    if (el.id === payload.id) {      el.quantity += payload.quantity      itemfound = true    }  })  if (!itemfound) state.cart.push(payload) }

We can now use a getter in the store to calculate the total, which is what we’ll eventually pass to our Stripe serverless function (the other post picks up from here). We’ll use a reduce for this as reduce is very good at retrieving one value from many. (I wrote up more details on how reduce works here).

cartTotal: state => {  if (!state.cart.length) return 0  return state.cart.reduce((ac, next) => ac + next.quantity * next.price, 0) }

And there you have it! We’ve set up individual product pages, and Nuxt generates all of our individual routes for us at build time. You’d be Nuxt not to try it yourself. 😬

The post Creating Dynamic Routes in a Nuxt Application appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]