Building a Wedding Invitation Mini Program with WeChat

Project Overview

This wedding invitation mini program consists of five distinct pages: the main invitation view, a photo gallery, a video memories section, a venue map, and a guest response form. Below is a brief introduction to the functionality of each section:

  • Invitation View: Displays the couple's avatars, names, wedding date, time, and location, alongside quick-dial buttons for the bride and groom.
  • Photo Gallery: Showcases happy moments of the couple using a vertical image carousel.
  • Memories Section: Utilizes video components to documnet the couple's journey.
  • Venue Map: Integrates maps to help guests navigate to the wedding location.
  • Guest Form: Allows attendees to RSVP, select the number of guests, and leave blessings.

Project Initialization

Start by creating a blank project in the WeChat Developer Tools. You need to define the page routes and global styles in app.json.

{
  "pages": [
    "pages/home/home",
    "pages/gallery/gallery",
    "pages/memories/memories",
    "pages/location/location",
    "pages/rsvp/rsvp"
  ],
  "window": {
    "navigationBarBackgroundColor": "#ff4c91",
    "navigationBarTitleText": "Wedding Invite",
    "navigationBarTextStyle": "white",
    "backgroundTextStyle": "light"
  },
  "tabBar": {
    "list": [
      {
        "pagePath": "pages/home/home",
        "text": "Invitation",
        "iconPath": "assets/icon_invite.png",
        "selectedIconPath": "assets/icon_invite_active.png"
      }
      // ... other tab items
    ]
  }
}

Invitation Page (Home)

Background Music Control

The page features a toggle button in the corner to play or pause background music. The logic checks the current state and trigggers the appropriate audio method.

home.wxml

<view class="audio-control {{isMusicOn ? 'playing' : 'paused'}}" bindtap="toggleAudio">
  <image src="/assets/music.png" />
</view>

home.js

toggleAudio: function () {
  if (this.data.isMusicOn) {
    this.backgroundAudio.pause();
  } else {
    this.backgroundAudio.play();
  }
  this.setData({ isMusicOn: !this.data.isMusicOn });
}

Quick Dial Feature

Implement one-tap calling using the wx.makePhoneCall API.

contactGroom: function () {
  wx.makePhoneCall({ phoneNumber: '13800138000' })
},
contactBride: function () {
  wx.makePhoneCall({ phoneNumber: '13800138001' })
}

Photo Gallery (Vertical Carousel)

The gallery uses a vertical swiper component that auto-plays and loops through images.

gallery.wxml

<swiper vertical circular autoplay interval="3000" duration="500" indicator-dots indicator-color="#fff" indicator-active-color="#e91e63">
  <swiper-item wx:for="{{photoList}}" wx:key="id">
    <image src="{{item.src}}" mode="aspectFill" />
  </swiper-item>
</swiper>

gallery.js

data: {
  photoList: [
    { id: 1, src: '/images/pic_01.jpg' },
    { id: 2, src: '/images/pic_02.jpg' },
    { id: 3, src: '/images/pic_03.jpg' }
  ]
}

Memories Page (Video Integration)

This section uses the <video> component. It also demonstrates how to handle timestamp formatting using WXS (WeiXin Script) for dynamic data display.

memories.wxml

<wxs module="dateFilter">
  module.exports = function(ts) {
    var d = getDate(ts);
    return d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate();
  }
</wxs>

<view class="video-container" wx:for="{{videoList}}" wx:key="id">
  <view class="title">{{item.title}}</view>
  <view class="date">Date: {{dateFilter(item.timestamp)}}</view>
  <video src="{{item.url}}" controls></video>
</view>

memories.js

data: {
  videoList: [
    { id: 1, title: 'Seaside Memories', timestamp: 1532519777690, url: 'http://example.com/video1.mp4' }
  ]
}

Wedding Location (Map Integration)

Use the <map> component to mark the venue. Clicking the marker opens the native WeChat map for navigation.

location.wxml

<map longitude="{{lng}}" latitude="{{lat}}" scale="16" markers="{{markers}}" bindmarkertap="openNavigation"></map>

location.js

data: {
  lat: 40.06021,
  lng: 116.3433,
  markers: [{
    id: 1,
    latitude: 40.06021,
    longitude: 116.3433,
    iconPath: '/assets/marker.png',
    width: 40,
    height: 40
  }]
},
openNavigation: function() {
  wx.openLocation({
    latitude: this.data.lat,
    longitude: this.data.lng,
    name: 'Wedding Venue',
    address: 'Some Street, Haidian District'
  });
}

Guest RSVP Form

Form Structure and Picker

The form collects user info. A picker component is used to select the number of attendees.

rsvp.wxml

<form bindsubmit="submitForm">
  <input name="username" placeholder="Your Name" bindblur="validateName" />
  <input name="mobile" placeholder="Phone Number" bindblur="validatePhone" />
  
  <picker bindchange="changeCount" value="{{countIndex}}" range="{{countArray}}">
    <view>Guests: {{countArray[countIndex]}}</view>
  </picker>
  
  <input name="blessing" placeholder="Leave a blessing" />
  <button form-type="submit">Submit RSVP</button>
</form>

Validation Logic

Validate the name and phone number using regular expressions when the input loses focus.

validateName: function(e) {
  const nameReg = /^[\u4E00-\u9FA5A-Za-z]+$/;
  if (!nameReg.test(e.detail.value)) {
    wx.showToast({ title: 'Invalid Name', icon: 'none' });
  }
},
validatePhone: function(e) {
  const phoneReg = /^1[3-9]\d{9}$/;
  if (!phoneReg.test(e.detail.value)) {
    wx.showToast({ title: 'Invalid Phone Number', icon: 'none' });
  }
}

Subscription Messages

To send a notiifcation after submission, request permission using wx.requestSubscribeMessage and exchange the login code for an openid via the backend.

submitForm: function(e) {
  wx.login({
    success: (loginRes) => {
      // Simulated server request to exchange code for openid and send message
      wx.request({
        url: 'https://your-api.com/send-rsvp',
        data: {
          code: loginRes.code,
          formDetails: e.detail.value
        },
        success: () => {
          wx.showToast({ title: 'RSVP Successful!', icon: 'success' });
        }
      });
    }
  });
}

Tags: WeChat Mini Program wx.requestSubscribeMessage wx.makePhoneCall swiper component map component

Posted on Mon, 12 Oct 2026 16:51:28 +0000 by TGixer