Today I Learned...

#8   Vue3: <select> default value

Posted: 06.11.2020

Cost me more time than I anticipated, esp. due to the fact that it only happened for production builds.

So, in order for a <select> (with an Object-based v-model) to properly display its default value in Vue 3 (3.0.2), this had to be done:

<select ... v-model.lazy="selected" @change="update(selected)">
  <option disabled :value="{}" :selected="selected === {}">Select Something...</option>
  <option v-for="(item, index) in list" :key="index" :value="item">{{ item.title }}</option>
</select>

The :selected="selected === {}" was necessary, as the <select> would otherwise display as a blank box once the v-for rendered <option> elements came in.

Again, this only happened in production, local dev builds did not behave that way which made it extremely frustrating to debug.

Probably worthy of further investigation and a report to the Vue team, but I don’t have time to try and get a reproducible example done at the moment.

#7   Vue3: "click outside" directive

Posted: 10.10.2020

Directives are quite different in Vue 3 - see: Vue 3 docs

Here’s what I came up with for a simple “close an element (modal etc.) when a click outside of this element registers” directive. Clicks on elements within the target element and elements with the class click-outside-ignore will be ignored.

The function/method to close the element is registered as binding.value, so when using it on a component, it should look like this: <Component v-click-outside="closeComponent" />

let handleOutsideClick = null;

app.directive('click-outside', {
  beforeMount(el, binding, vnode) {
    handleOutsideClick = (e) => {
      e.stopPropagation();
      if(!el.contains(e.target) && !e.target.classList.contains('click-outside-ignore')) {
        binding.value();
      }
    }
    document.addEventListener('click', handleOutsideClick);
    document.addEventListener('touchstart', handleOutsideClick);
  },
  beforeUnmount() {
    document.removeEventListener('click', handleOutsideClick);
    document.removeEventListener('touchstart', handleOutsideClick);
  }
});

#6   Hugo: RSS feed duplication

Posted: 01.09.2020

Checking Google Search Console earlier this week made me notice that Hugo created duplicates of my RSS feed in strange places like /tags/feed.xml and /tags/tagname/feed.xml.

After a quick look at the Hugo documentation, I found out that this behaviour seems to be the default for pages of the kind taxonomy and term - seems I forgot about that or never even noticed it in the first place…

Conclusion: I had to change the [outputs] section of my config.toml from this:

[outputs]
    home = ["HTML","RSS"]
    section  = ["HTML"]

To this:

[outputs]
    home = ["HTML","RSS"]
    section  = ["HTML"]
    taxonomy  = ["HTML"]
    term  = ["HTML"]

#5   Android: use ADB to uninstall bloatware

Posted: 14.08.2020

I recently got the Android 10 update and had to factory reset my phone thanks to the phone’s language settings not sticking anymore. Factory reset unearthed all the bloatware again that I had gotten rid of years ago, so I also had to do that again.

Here’s a quick reminder of how to do that:

  1. Get ADB platform tools for your OS
  2. On your phone: enable developer mode and USB debudding
  3. Connect phone
  4. Test if connected successfully and allow debugging (will be prompted): adb devices
  5. adb shell to get into the phone
  6. List packages with pm list packages | grep 'pkg.name.etc' or search for them like this: pm list packages -f TESTPKG
  7. Uninstall bloatware like this: pm uninstall -k --user 0 com.android.google.youtube
  8. See bloatware disappear 😁

Based on this guide at xda: How to Uninstall Carrier/OEM Bloatware Without Root Access

#4   Shell Script: launch VS Code for a specific folder/repository

Posted: 24.07.2020

I wanted to have an easy way to launch VS Code for specific repositories and came across the code PATH-TO-REPO command.

This little shell script will open a specific folder/repository based on an argument given to it or based on a directory listing of the /home/user/Repos folder:

#!/bin/bash

# get param
repo=$1

if [ -z "$repo" ]
  then
    # check first
    ls /home/USER/Repos/

    # ask user for input
    echo -n "which repo: "
    read repo
  else
    echo "opening "$repo
fi

code /home/USER/Repos/$repo

I’ve also configured an alias for that script; simply typing lcode REPO-NAME now opens VS Code for that folder/repository.

#3   Vue.js: handle component's click event in its parent

Posted: 17.07.2020

Use case: a component creates nothing but a <button> with a slot that handles its display state internally but hasn’t got any actual functionality; the handler method is defined in the parent.

In this case, @click.native has to be used to call the method defined in the parent:

// in parent component

<cButton @click.native="theMethod(praram)">Button Name</cButton>

#2   Manjaro Linux mount script: BitLocker encrypted external drive

Posted: 12.07.2020

Got a new external USB 3.0 drive and set up BitLocker encryption. Manjaro (Dolphin) couldn’t really do anything with it, kept prompting for the pwd but didn’t mount it.

I ended up writing my own mount script that works well so far:

#!/bin/bash

# check first
lsblk -f

# ask user for input
echo -n "input details (fstype bitlocker): "
read device
read -sp 'Magic powder: ' mgk

# mount according to user input
sudo fusermount -u /media/data/drive/ # unmount in case it's still mounted for some reason
sudo dislocker -V /dev/$device -u$mgk -- /media/data/drive
sudo mount -o loop /media/data/drive/dislocker-file /media/data/drive-mnt

echo mounted drive

It lists connected block devices first (lsblk), so it’s not hardcoded to sda/sdb in case that ever changes. Need selection of whatever mentions BitLocker, then asks for the encryption key/pwd and proceeds to mount the drive with dislocker. Folders used in /media/data/ need to exist before the script is executed.

#1   Manjaro Linux: .service file error when setting up KeeWeb

Posted: 10.07.2020

Installed KeeWeb on Manjaro and got the following error:

The name org.freedesktop.secrets was not provided by any .service file

Resolution: had to install a package called gnome-keyring.