Saturday, June 23, 2018

Scaffolding a new Vue.js component

I've been working for the past few months on a travel portal rewriting parts of it from old jQuery code to Vue.js - and learning a lot of stuff in the process. One thing that I learned the hard way is that scaffolding that's built in into Vetur is just not for me. It is too simple.

The naming convention we have for our component files is for them to have the same name as the file they exist in. So basically TestMe.vue becomes

<template>
  <div class="test-me">
    ...content
  </div>
</template>

<script>
import Vue from 'vue'
import Component from 'component'

@Component({})
export default class TestMe extends Vue {
}
</script>

<style lang="scss" scoped>
.test-me {
}
</style>

Makes sense?

The problem is that having to type this in every time I create a new component (and the number of those grows like creazy!) is tedious. So I finally got to it and created a snipped that works for me:

That's it! You type "sfc", press [Tab] and the component is ready to be worked on by magic of the VS Code templating engine.

The first thing that'll be edited is the name of the exported class. If it is OK then just press [Tab] to move to the name of the CSS class. Edit it if you must then press [Tab] again and you'll be able to select the processor for styles. The next thing that you get to customize is if the styles should be scoped. Once on it either press [Tab] to go with scoped styles or [Delete] and then [Tab] to go without scoped styles. Finally you arrive at the Hello, world! text where the editing of your component begins.

Have a nice day!

Saturday, June 16, 2018

Vue.js - editor components

When talking about creating applications in Vue.js it is not hard to find one that does something to data. Obviously for state management there's Vuex, Redux and other stores but in this post we're going to focus strictly on passing state via props to components that one could generally call controls - so more on the lines of custom inputs.

The 3 cases

There are 3 cases that we will encounter when passing data down to controls:

  • We're passing in primitive values (strings, numbers, booleans)
  • We're passing in complex reactive objects (think: list of people)
  • We're passing in a complex reactive object but we'd like to treat it as a primitive and have atomic changes to all its fields

Primitives

In the case of primitives the situation is dead simple: use v-model, you can react to changes by hooking up to the input event - done. The documentation is fantastic in that area so if you'd like to know more about it dig in!

Reactive complex objects

Imagine you have a data structure like this:

data = { firstName: 'John', lastName: 'Doe' }

In this case if you create a control (we'll call it DataEdit.vue) that you'd like to immediately edit the fields you could do something like that:

<template>
  <div>
    <input v-model="value.firstName">
    <input v-model="value.lastName">
  </div>
</template>

<script>
export default {
  props: {
    value: Object
  }
}
</script>

This means that if used in a parent component (ContactForm.vue) like so:

<template>
  <div>
    <h1>{{ person.firstName }} - {{ person.lastName }}</h1>
    <DataEdit :value="person" />
  </div>
</template>

<script>
import DataEdit from './DataEdit.vue'

export default {
  components: {
    DataEdit
  },
  data() {
    return {
      person: { firstName: 'John', lastName: 'Doe' }
    }
  }
}
</script>

then changes to values in inputs in DataEdit.vue component will immediately be reflected in ContactForm.vue. Vue's reactive system at its best.

Treating complex objects like a value

This is the trickiest one because even though we're passing on a complex, reactive object we'd like to get all the changes at once or none at all. You might ask why would you want such a thing? The answer is quite simple: you'd like to implement "OK/Cancel" functionality or (if the edits drive some kind of Ajax requests) limit the number of actions upon edits. It is quite obvious that there will be a need for a copy of the reactive object. For that I use cloneDeep method from Lodash and it works just great so far.

<template>
  <div>
    <input v-model="internal.firstName">
    <input v-model="internal.lastName">
    <button @click="$emit('input', internal)>Save</button>
  </div>
</template>

<script>
import cloneDeep from 'lodash/cloneDeep'

export default {
  props: {
    value: Object
  },
  data () {
    return {
      internal: cloneDeep(this.value)
    }
  }
}
</script>

Now if that component is used in the ContactForm.vue (note the change from :value to v-model)

<template>
  <div>
    <h1>{{ person.firstName }} - {{ person.lastName }}</h1>
    <DataEdit v-model="person" @input="personUpdated" />
  </div>
</template>

<script>
import DataEdit from './DataEdit.vue'

export default {
  components: {
    DataEdit
  },
  data() {
    return {
      person: { firstName: 'John', lastName: 'Doe' }
    }
  },
  methods: {
    personUpdated(newValue) {
      console.log('Person has been updated to: ', newValue)
    }
  }
}
</script>

you won't see any changes to the header until they are saved by clicking the Save button. Pretty neat, right? On top of that you can be notified when the change occurred so if some additional action needs to take place (like updating list of people from an external database) by listening to the input event. That is just pure awesome!

One more thing...

If the editor persists it will now share the internal and value objects which will make it behave like the case where everything is reactive. Not good - let's do something about it

<template>
  <div>
    <input v-model="internal.firstName">
    <input v-model="internal.lastName">
    <button @click="$emit('input', internal)">Save</button>
  </div>
</template>

<script>
import cloneDeep from 'lodash/cloneDeep'

export default {
  props: {
    value: Object
  },
  watch: {
    value: {
      handler (newValue) {
        this.internal = cloneDeep(newValue)
      },
      deep: true
    },
  },
  data () {
    return {
      internal: cloneDeep(this.value)
    }
  }
}
</script>

The introduced watch updates the internal state so that it is again disconnected from the ContactForm.vue. Of course in a situation where the DataEdit.vue component is removed from DOM due to let's say closing a popup then the watch is completely unnecessary. It does however come in handy if there might be a possibility that the data object in question (or some of its parts) can be modified from the parent component. The internal state will be out of sync in such case. This might happen if some of the details come from an Ajax request or a timer. The watch covers both cases so it is basically a universal way for data synchronization on changes from parent component.

Working example

I know this is a lot to take in at once. Therefore I have prepared a test application for you that illustrates all the pieces. You can find it at https://github.com/padcom/vue-editor-components

That's it, folks!

Monday, April 9, 2018

Vue.js and functional single file components

Single file components (SFC) is probably the most powerful feature (structure-wise) in Vue.js. They are simple in nature but very powerful when it comes to bundling things together:

<template>
  <h1 class="my-header>Hello!</h1>
</template>

<script>
export default {
}
</script>

<style>
.my-header {
  color: red;
}
</style>

There are times when you want your component to be stateless. Such components are great for bundling together functionality that would otherwise be created by putting together other components. I call them template components, because they are predefined with places where you can override the defaults. Those components do not have state hence we call them stateless or functional.

The problem with SFCs is that unlike regular .vue components they don't pass data down. Especially the class and style properties are not passed automatically. To mitigate that I went through a few iterations to find the nicest solution. Here's what I came up with that seems to do the job very well. Let's assume we're creating a predefined component for animation. We want the styles to be bundled with the component so SFC is the right way to go.

<script>
export default {
  functional: true,
  render: (h, { data, children }) => (
    <transition-group { ...data } tag="ul" name="slide">
      { children }
    </transition-group>
  )
}
</script>

<style>
.slide-move {
  transition: transform 1s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
</style>

A quick explanation: { data, children } is a destructing assignment from the second parameter to 2 fields that we'll use later. Then the { ...data } means "apply all elements passed on (including but not limited to class and style).

That's all there is to it.

Thursday, March 22, 2018

HttpHandler registration on XSP4 vs IIS

The problem

You're developing an ASP.NET HttpHandler on Mono using XSP and now you need to deploy your app on IIS. What worked on XSP4 isn't working anymore and strange errors appear.

Let's start with the config that works on XSP4

<?xml version="1.0"?>
<configuration>
  <system.web>
    <httpHandlers>
      <add verb="*" path="*" type="MyHandler" />
    </httpHandlers>
  </system.web>
</configuration>

But you put that same Web.config file on IIS it throws errors.

The solution

As you see the registration happens inside system.web/httpHandlers section. That works on XSP4 and older ASP.NET but it's not the case on modern IIS. In there you need to switch to system.webServer/handlers section like this:

<?xml version="1.0"?>

<configuration>
  <system.webServer>
    <handlers>
      <add name="name" verb="*" path="*" type="MyHandler" />
    </handlers>
  </system.webServer>
</configuration>

That's it! Happy coding!

Wednesday, March 21, 2018

Getting started with POI and React

This will be a quick one and, quite frankly, a very obvious one. But since I forgot how it is done I better write it down for posterity (and me).

Setting things up

As always you'll need a folder. Let's call it my-example

$ mkdir my-example
$ cd my-example

Then we need to initialize our project:

$ npm init

and accept all the defaults.

Next we need a few packages installed:

$ npm install poi react react-dom --save-dev

Creating poi.config.js

Since by default POI compiles JSX down to Vue's interpretation of what JSX is we need to tell it to use React's JSX compilation. We do that by adding the poi.config.js file with the following content:

module.exports = {
  jsx: 'react'
}

Creating start script

Finally, to make our project setup complete we should add a start script to package.json to make use of the locally installed POI:

"scripts": {
  "start": "poi"
}

Time for a simple app

With all that setup all there is to it is to test it with some React components. For that we will create index.js with the following content to display a Hello, world!-type app:

import React from 'react'
import ReactDOM from 'react-dom'

ReactDOM.render(<h1>Hello, world!</h1>, document.getElementbyId('app'))

And just like that, in under 3 minutes, by the magic of POI, we have a fully-working application that can be developed, tested and built for production deployment. I like it!

Happy coding!

Big Fat Ass - Windows + Visual Studio

Warning: this post contains bad language, obscene descriptions and a lot of frustration. Don't read it if you're sensitive.

The fucking nightmare

In the past I used to work with Windows. I liked it - especially Windows 2000 and then XP. It was kind of fresh, you know? Still looking the same as the old win but kinda... better. And after a few small upgrades to the hardware, like a tiny bit more RAM, it worked really fast. I was reluctant to look for other OSes for more reasons than just I got used to it: Delphi, the IDE I was working most of the time in, was not available on other platforms. And I loved Delphi. It was the best thing ever! Especially the Personal edition which was bloody fast and easy to use.

At one point I gave Linux a try. Slackaware to be precise. I felt this was not just for me but also not for any sane human being. I mean come on: compile kernel just to be able to install the distro? Are you fucking kidding me? Then I gave RedHat a try. Well.. better but still: 24 floppies just to install the basic OS? Are you fucking kidding me?!!! And then Ubuntu came along a few years later. I ordered the CD (good old days :D), installed it and liked it instantly. It looked different, foreign... but nice. I got along with the keyboard quite fast, cmd was finally bash and way more humane to work with... Basically, for the first time I didn't immediately went with "You have to be shitting me, man! What a shit hole!". But I was still a Delphi developer so it was more for entertainment than anything else...

Fast forward a few years and that stopped being a problem since I moved to Java.

2018

It's 2018. I work exclusively in Linux, I love every bit of it. I like that I can choose not to butcher my computer with CPU/GPU-intensive operations just to show the content of a fucking folder. I'm loving XFCE and everything about it. I use Linux Mint and my main occupation is frontend development so Windows is pretty much useless anyways. I play on Linux, I watch movies on Linux, I work on Linux. And everyone in my family does too and they like it! My distro of choice is Linux Mint because it is the closest approximation of Windows XP I can get out of the box. And it is good!

And then I decided to give .NET a spin... Man,.. there are decisions that one regrets moments after they are made. At first it wasn't so bad. I still used Linux with Mono, tried Core but it wasn't the right target I was looking for so Mono was the option. Everything seemed to work just fine, MonoDevelop rocks! Fast, easy, nice... I like. I even completed the entire project, was able to test it using XSP...

All was good just up to the point where I needed to test it in real conditions. NOTHING FUCKING WORKED! NOT A SINGLE FUCKING THING! JAVA KILLER MY ASS!!!

So basically creating a solution in MonoDevelop does not mean you will be able to load it into the latest Visual Studio. Windows, when I turned it on, immediately started taking over my CPU fan, spinning it so fucking fast the whole machine became more than just a bit warm. It was FUCKING HOT!!! And still... nothing fucking worked!!!

After a trial and error, looking at Stack Overflow and other enlightened sites I finally was able to throw away all the project files, recreated them in VS 2017 and then it still didn't fucking work! All because some idiot decided to switch from one XML configuration section to another. I mean for the love of God, really?! WHAT THE FUCK!?!?

It took me a better part of this evening to just get it started, then about 3 minutes to add a portion to my node module that converts from fucking backslashes to forward slashes (as though the rest of the fucking world were morons and used the wrong character for path separator) and I was finally on my marry to start hating Windows on my blog.

Post mortem

Unfortunately, as a front developer I need to have access to Edge which, surprise surprise!, is only available on fucking Windows. And this is the only reason I have a separate, dual boot notebook that runs a legal (my God, what a fucking waste of fucking hard earned money) copy of Windows 10.

I need a fucking drink after all this. No wonder .NET developers are so strange... there is a damn good reason for it!

God save us from Windows and .NET. Please!!!

Monday, January 29, 2018

Side project: getting eyes far away

Last year I became obsessed with FPV. I don't mean games - that's kinda for kids. I'm talking here about getting an object, a plane in this case, equipped with a camera and other equipment that can be controlled from a distance. I was trying to get into the multi-rotor business but that seems not to be my thing. Planes, on the other hand, are. So I tried my luck there...

My first time was... well... exciting wouldn't even begin to cover it! It was a mysterious experience! I was actually in a plane that flies around, hundreds of meters away from me, seeing the real life flashing before my eyes. It was simply a blast! But as soon as I flew the first time and saw the land that I already covered something woke up in me: the nagging question what is out there? I guess I am kind of an explorer down deep inside :) And so I begun to cover more and more ground. It soon was pretty clear for me that the equipment I had at the time with a 200mW VTX was not going to quite cut it. All that was made crystal clear for me once I lost the plane after just several hundred meters flight in the neighborhood. It sucked big time and about 600 PLN was forever lost. Sometimes when I drive around I hope to see this plane hanging out in some tree but that didn't happen.

Someone could say: this is way too expensive and too dangerous - but not me. I came back home, late at night that day, and immediately ordered a stronger VTX (used to ride a 200mW one, now I ordered a 600mW ImmersionRC that people said was good for several kilometers!). It took a while before I was able to get back up in the sky but it eventually happened. With the new VTX, a changed site and a new plane I was rocking the sky again!

Over the course of last summer I didn't loose a plane (well, technically I did but more on that later or). I was flying first 1.3km to a landmark I knew and I was passionate to get to. That didn't work because of the antennas that I had. That day I learned that power is not everything - you need to have something to convey it with. And in the case of video transmission (and also the control transmission from your radio to the plane) antennas are the holy grail! So I went ahead and bought 3 of the most recommended (and most sexy) ones - the Aomway clover leave antennas. Alongside the 600mW VTX I also bought a 14dBi directional patch antenna. Using this setup I was finally able to easily break the 2km range!

But my appetite (and the addiction) grew...

So I started experimenting. First about going further than 2km. It turned out that the 100mW OpenLRS system wasn't all that good at ground leve. - so I built a 2m mast that gave me more range. A few weeks later I tested it up to 4.8km and let me tell you the wiggles that I have had that day were nothing compared to the first time with a woman! I was so fucking stressed out I almost fainted!

All things considered it was a pretty good flight. I used a 3s 3000mAh Li-on pack at that flight and it almost lasted to get the plane home. Just a few tents of meters over a field and the plane was safe and sound in my hands. That meant I needed more power. Lot's of it.

In a situation like that power comes from a combination of input voltage, amps, ESC, motor and propeller. So I started looking for the best combination. Just out of share luck I have had a few od 2212 810kv motors around (from my failed attempt to build a 450-sized quadcopter). I thought, since it had the required max thrust (around 1kg) so why I don't I give it a shot. And so I did!

The first attempt was very promising. At 4S and a 10x4.5 prop it flew great and I was able to finally reach the 5km mark. I turned back to see how the battery will behave on the way but it was plenty left. That encouraged me to give it another shot the next day and... that is how I achieved my up-to-date record of 8.2km out and safely back!

Oh boy was I excited! All my efforts were finally paying off! My dream was to take the plane from the place where I was usually flying back to the place I live - which was about 6.5km away. With the record flight of 8.2km I thought it was a no brainer. Man, was I wrong! It's not just the tx/rx/antennas combination but first and foremost the lay of the land that allows (or not) to get to longer distances. Luckily the day before that I have put my phone number and since the plane automatically landed on a busy street and a good man picked it up and called me the plane was recovered - and my ambition was greatly humbled.

This year I'm trying my luck in the same direction that my record flight of 8.2km was. I am hoping to break through the 20km barrier with some new equipment that I have bought:

  • 500mW Wolfbox TX (with potential to be modded to 1W)
  • 1W VTx and a biquad 11dBi antenna that I tested up to 12km with crystal clear picture on the ground
  • an all new Mini Talon with 4S2P Li-on battery pack

The plan is as follows:

  • First do a maiden of the plane with the minimum electronics to get it to fly
  • Add a flight controller for stabilization and get it to work as expected (F4 AIO FC with OSD)
  • Do a test flight over a 1km distance with the lest powerful antennas I have to check the viability of the video down and control up link
  • Do a endurance test with all equipment to see how long will the battery will last at what speeds - hope to get at least 40km range before the batteries are all dead)
  • Get back to the 5km mark and back
  • Get past the 10km mark and back
  • Get past the 15km mark and get back
  • Get past the 20km mark and get back

I have no idea if this is going to work or not. I truly don't! But I hope one day I'll have a video to show you how the flight went and what emotions it gave me!

Happy flying!