/ Gists / Vue.js

Gists - Vue.js

On gists

Card number - space after each 4 digit & only digit control

Vue.js

component.vue #

<!-- https://javascript.plainenglish.io/vue-get-input-value-206d5adc832c -->

<template>
  <div id="app">
    <input
      type="text"
      :value="cardNo"
      placeholder="Card number"
      @input="handleInput"
      @keypress="handleKeyPress"
    />
    <br />
  </div>
</template>
<script>
export default {
  data() {
    return {
      cardNo: '',
    };
  },
  methods: {
    handleInput(event) {
      this.cardNo = event.target.value
        // Remove spaces from previous value
        .replace(/\s/g, '')
        // Add a space after every set of 4 digits
        .replace(/(.{4})/g, '$1 ')
        // Remove the space after the last set of digits
        .trim();
    },
    handleKeyPress(event) {
      const num = Number(event.key);
      const value = event.target.value;
      // Only allow 16 digits
      if ((!num && num !== 0) || value.length >= 16 + 3) {
        event.preventDefault();
      }
    },
  },
};
</script>

On gists

Debounced method in Vue (settimeout), fetch with cors mode

JavaScript Vue.js

example.js #

  methods: {
    search() {
      clearTimeout(this.timeout)
      this.timeout = setTimeout(() => {
        this.findSong()
      }, 500)
    },

    async findSong() {
      let headers = new Headers()
      headers.append('Content-Type', 'application/json')
      headers.append('Accept', 'application/json')
      headers.append('Origin', 'http://vue3.rjwebdesign.cz')
      headers.append('GET', 'POST', 'OPTIONS')

      let q = encodeURI(this.q)
      if (!this.q) {
        return
      }

      //console.log(q)
      // return

      const response = await fetch(`https://itunes.apple.com/search?term=${q}&limit=50`, {
        mode: 'cors',
        method: 'POST',
        headers: headers
      }).catch(err => console.log(err))

      const data = await response.json()
      this.songs = data.results.filter(item => item.kind == 'song')
      console.log(this.songs)
    },

On gists

Multi-file single-file components (external files)

Vue.js

vuecomp.vue #

<!-- A "single" file component -->
<template src="./template.html"></template>
<script src="./script.js"></script>
<style scoped src="./styles.css"></style>

On gists

How to make a variable created outside of Vue reactive - Options API

Vue.js

example.js #

// options API

const externalVariable = getValue();

export default {
  data() {
    return {
      reactiveVariable: externalVariable,
    };
  }
};


On gists

Composable: useMouse

Vue.js

useMouse.js #

import { ref, onMounted, onUnmounted } from 'vue'
export function useMouse() {
  const x = ref(0)
  const y = ref(0)
  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }
  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))
  return { x, y }
}



// usage
<template>
  X: {{ x }} Y: {{ y }}
</template>
<script setup>
  import { useMouse } from './useMouse';
  const { x, y } = useMouse();
</script>


// with params = config
// Using an options object
const title = useTitle('A new title', { titleTemplate: '>> %s <<' });

// or with many params
const title = useTitle('A new title', '>> %s <<');


export function useMouse(options) {
  const {
    asArray = false,
    throttle = false,
  } = options;
  // ...
};

On gists

Click to (fake click aka teleport link)

Vue.js

clickTo.js #

const redirect = target => {
  document.querySelector(target).click()
}

export default {
  install(Vue) {
    Vue.directive('click-to', {
      mounted: function (el, binding) {
        el._clickRedirectCallback = () => redirect(binding.value)
        el.addEventListener('click', el._clickRedirectCallback)
      },
      unmounted: function (el) {
        el.removeEventListener('click', el._clickRedirectCallback)
      }
    })
  }
}

On gists

Composition examples & ways

Vue.js

examples.js #

<template>
    <div>
        <p>Spaces Left: {{ spacesLeft }} out of {{ capacity }}</p>
        <h2>Attending</h2>
        <ul>
            <li v-for="(name, index) in attending" :key="index">
                {{ name }}
            </li>
        </ul>
        <button @click="increaseCapacity()">Increase Capacity</button>
    </div>
</template>
<script>
import { ref, computed } from 'vue';
export default {
    setup() {
        const capacity = ref(4);
        const attending = ref(['Tim', 'Bob', 'Joe']);
        const spacesLeft = computed(() => {
            return capacity.value - attending.value.length;
        });
        function increaseCapacity() {
            capacity.value++;
        }
        return { capacity, attending, spacesLeft, increaseCapacity };
    },
};
</script>


// can be rewritten as:
import {
    reactive,
    computed,
    toRefs
} from "vue";

export default {
    setup() {
        const event = reactive({
            capacity: 4,
            attending: ["Tim", "Bob", "Joe"],
            spacesLeft: computed(() => {
                return event.capacity - event.attending.length;
            })
        });

        function increaseCapacity() {
            event.capacity++;
        }
        return {
            ...toRefs(event),
            increaseCapacity
        };
    }
};


// TO ORGANIZE BY FEATURE
<template>…</template>
<script>
export default {
    setup() {
        const productSearch = useSearch();
        const resultSorting = useSorting({});
        return { productSearch, resultSorting };
    },
};

function useSearch(getResults) {}
function useSorting({ input, options }) {}
</script>


// TO EXTRACT SHARED CODE:
<template>…</template>
<script>
import useSearch from '@use/search';
import useSorting from '@use/sorting';
export default {
    setup() {
        const productSearch = useSearch();
        const resultSorting = useSorting({});
        return { productSearch, resultSorting };
    },
};
</script>

// use/search.js 
export default function useSearch (getResults) { }

// use/sorting.js 
export default function useSorting ({ input, options }) { }

On gists

Composable - replacement for VUEX

Vue.js

example.js #

// https://medium.com/js-dojo/should-you-use-composition-api-as-a-replacement-for-vuex-274356443ebc

// src/global.js
import { reactive, readonly } from "vue";
const state = reactive({
  count: 0
});
const increment = function () {
  state.count++;
}
export default { state: readonly(state), increment };

// src/main.js
import { createApp } from "vue";
import global from "@/global";
const app = createApp({
  provide: {
    global
  },
}

// someComponent.vue
<template>
  <div>{{ global.state.count }}
  <button @click="global.increment">Increment</button>
</template>
<script>
export default {
  inject: ["global"]
}
</script>

On gists

VUEX store in latte template

Vue.js AW

some.latte #

$store.state.modalForm.formId
$store.dispatch('modalForm/close')


  <a 
    @click="$store.dispatch('modalForm/open', { 
        formId: {$data->button__contact_form_section->contact_form_control_id}, 
        sectionId: {$data->button__contact_form_section_id} 
    })"
    class="Btn Btn--Primary cursor-pointer">
    {$data->button_text}
</a>

On gists

Handle Multiple Promises using Async/Await

Vue.js

examples.js #

// https://medium.com/@matodev/handle-multiple-promises-using-async-await-1a05b26dafba

// The wrong and slow way

userIDs = ['fooID1', 'fooID2', ...]
const slowMethod = async (userIDs) => {
    const results = [];
    for (let i = 0; i < userIDs.length; i++) {
        const res = await fetch(`https://api.foo.com/users?uid=${userIDs[i]}`)
        const data = await res.json()
        results.push(data);
    }
    return results;
}
await slowMethod(); //O(n) time



// ✔️ The Fast Way

userIDs = ['fooID1', 'fooID2', ...]
const fastCleanMethod = async (userIDs) => {
    const promises = userIDs.map(async userID => {
        const res = await fetch(`https://api.foo.com/users?uid=${userID}`);
        return await res.json();
    });
    return await Promise.all(promises);
}
await fastCleanMethod(); //O(1) time



// ❌ Fast but Fails Slow

const getUserData = async (userIDs) => {
    const userDataPromise = fetch(`https://api.foo.com/users?uid=${userID}`);
    const userEntriesPromise = fetch(`https://api.foo.com/entries?uid=${userID}`);

    const [userDataRes, userEntriesRes] = [(await userDataPromise).json(), (await userEntriesPromise).json()];
    const [userData, userEntries] = [await userDataRes, await userEntriesRes];
    return {
        ...userData,
        userEntries,
    }
}


// ✔️ Fast and Fails Fast

const getUserData = async (userIDs) => {
    const userDataPromise = fetch(`https://api.foo.com/users?uid=${userID}`);
    const userEntriesPromise = fetch(`https://api.foo.com/entries?uid=${userID}`);

    const [userDataRes, userEntriesRes] = await Promise.all([userDataPromise, userEntriesPromise]);
    const [userData, userEntries] = await Promise.all([userDataRes.json(), userEntriesRes.json()]);
    return {
        ...userData,
        userEntries,
    }
}