Components in a static site too

In the 2nd part of this series, we learned about some basics of rendering a view. We ended that topic by having a look at the router. The router just had one path, the root (/), which was mapped to a single component called the HelloComponent.

Here’s what we’ll do in this post:

  • Examine the HelloComponent
  • Add a new route, and a new component to handle the route
  • Add a nav link to take the user to the new route
  • Render another component inline without routing

HelloComponent

As you can see, the HTML code for most of what you see when you navigate to http://localhost:8080 comes from this file. So how does Vue know where to render the contents of this component? If you recall, the App.vue, the parent component, has a tag called and I mentioned that this is the output for any component that is routed to by the router.

Add a new route, and a new component to handle the route

Create a new file under the components/ folder. Let’s call it TestComponent.vue. And paste the following content.

Yes, I realize it doesn’t do much. I wanted to show you what a basic component looks like. It doesn’t need to have anything more than just that. With just that much content, you get a valid component. You should be able to imagine now, how easy it is to create a component and have your entire site split into pieces (components), that all come together eventually in the browser.

But wait. We are not done adding the component. We just added a file called TestComponent.vue but we haven’t really used it anywhere. So let’s add a new route to the router/index.js file.

Your router should now look like this:

We just added a new route to the router called /test, which routes to the newly-created TestComponent. Let’s test this out by going to: http://localhost:8080/#/test. You should see most of the content replaced with just the word “Test”. This means our new component has rendered. Great. We confirmed our new component to be working by manually going to the /test route.

Add a nav link to take the user to the new route

Let’s look at adding a route-link so that the user can navigate to this newly-created component of ours. Update the App.vue with this. Somewhere inside the <template> tag, add this markup

<router-link to="/test">Go to Test</router-link>

Vue will take care of the rest. It will render the router-link as an anchor (<a>) tag. You could do this programmatically too, if you don’t want to use an anchor tag. Refresh your browser and you should see a Go to Test link on your page. Click it. You should now see the contents of the TestComponent. That was it.

That’s it. We just learned how to use components in Vue to compose our app of little pieces, which are building blocks for a larger site or web app. I highly recommend reading more about VueRouter here.

Render another component inline without routing

So we saw how we could link to a custom component. What if we simply want to render another component inline, in the context of a parent component? Yep. You can do that too.

To do that, let’s first remove the <router-link> tag, and update your App.vue to this:

Then, go to http://localhost:8080 and you should see the contents of the TestComponent rendered inside the contents of App.vue, which also happens to consist of the contents from HelloComponent. So instead of replacing the contents from HelloComponent, we just augmented the contents of our new component in there.

Since you are rendering the component inline, there is no need for that new route that we added to the router/index.js. You can remove the /test route from it as well, if you’d like.

 

Advertisements

VueJS basics

his is the second part in a series of articles I am writing about how I used VueJS to build a static site.

Assumptions for this article

  • You have NodeJS 8.x installed with npm.
    • You can verify your installation by running these commands in a PowerShell window,
node --version
npm --version
  • You have some knowledge of CLI-based bootstrapping, and development.
  • You are using some sort of a web development IDE. I highly recommend VS Code.

Setup

You’ll want to get the official Vue CLI first. Be sure to install the latest stable release of the CLI. There is a beta version out there. At the time of this writing, 3.0 is still in beta so you can refer to the README for the 2.x version on the master branch. Then, run:

npm install -g vue-cli
vue init webpack my-project

Go through the prompts in your shell and complete the boilerplate project setup. These are my settings:

? Project name static-site
? Project description A Vue.js project
? Author Blog Author <author@blog.com>
? Vue build runtime
? Install vue-router? Yes
? Use ESLint to lint your code? Yes
? Pick an ESLint preset Standard
? Set up unit tests Yes
? Pick a test runner karma
? Setup e2e tests with Nightwatch? Yes
? Should we run `npm install` for you after the project has been created? (recommended) npm

You’ll notice that I used the word webpack in the command to create the project. That’s the name of the webpack template in the CLI. The CLI will automatically create the necessary webpack base configuration with all the loaders, extractors etc.
Once you are done with the setup, you can start-up your dev server for local development using:

npm run dev

You can access the local server using http://localhost:8080. This is it for setup. For most static sites, I don’t anticipate any changes in the base webpack config. So you don’t have to meddle with it at all, not even when you are ready to build a distribution package.

Basics

The sweet spot, in my opinion, for developing using Vue is, its single-file components. Everything that a component needs, the HTML template, the script, and the CSS (or SCSS, if you are living in the 21st century), is in the same file. This encourages you to split your site (or app) into simpler components that do only one thing. It encourages you to use the parent-child communication pattern effectively by way of props.

I won’t go over everything from the excellent documentation on VueJS’ docs site. But I will go over some of the basics, that I think are important before I explain how I built Net Your Problem.

Declarative Rendering

This is just a fancy way of saying, HTML in; HTML out. There is no special language for you to learn here. Of course, this doesn’t do much other than render the view (the HTML).

Open the App.vue file from the project you setup using the CLI and look at the content within the enclosing <template> tag.

and then in main.js:

All this is doing is, creating a new instance of a Vue app, and then binding the app instance to the root view, which is an element with the ID value “app”. As you can see, in App.vue, this is our <div> tag.

OK. But wait. How did Vue know where to look for an HTML element inside the App.vue component. Take a look at the “render” property in the statement for creating a new instance of a Vue app. Its value is an arrow function that accepts a callback function as a parameter. The callback function expects a Vue component to be passed to it. This render function is what kicks-off the render-ing of all child components when you start composing components from the parent component.

Data binding, conditional rendering and loops

A very important building block for any site, application. I am pretty sure almost every single site, web app out there uses conditional rendering and repeated elements all over.

Let’s modify the App.vue like this:

Now, reload the page. You should see the message Hello, World! right below the logo. If you change the value of the showMessage property from true to false, then you should see the message disappear. This was made possible because of the directive v-show. You can read more about conditional rendering and the other directive called v-if. There is an important performance difference between the two.

Let’s add a repeated element. Modify the App.vue’s template contents like this:

If the page hasn’t refreshed, refresh it, and you should see the additions. The condition items.length > 0 is satisfied since the items array has a non-zero size.  We only used a single <li> tag in the template, however, the final result has two of those. That’s because of the v-for directive. You can read more about it in the list rendering section of the guide.

Routers

Web sites, and web apps use URLs to send the user to new sections of a page, or to completely different pages. Routers are used to load/unload components as the user navigates your site/app. Depending on how you structure your site, you may or may not want to use a router at all. It isn’t necessary if you don’t have complex sections in your site, and you don’t need to orchestrate showing and hiding these sections appropriately.

But let’s walk-through it real-quick. If you recall in App.vue, there is a tag called <router-view/>. This is a special tag, which Vue recognizes as the output of a user navigation. That is, when the user navigates somewhere, the Vue system places the content of the new destination in its place.

Have a look at the router/index.js

That is it for some of the basics. I highly recommend reviewing the introduction to Vue’s concepts. You can read about them here.

Building a static site with VueJS

Disclaimer: The owner of Net Your Problem is my girlfriend.

This post is the first part of a series of articles. The project that I will focus on will be the site I recently developed for Net Your Problem; a company that connects fishermen with companies that recycle old and worn-out nets, in order to produce plastic pellets, which can be turned into new plastic products. If you are a fisherman, or a company that recycles nets, I highly recommend contacting Net Your Problem. I am not just recommending them, because I have a personal connection with the founder of the company. I truly believe in what they are doing.

I should also mention that since the time I built the site, the creator of VueJS announced a new framework, called VuePress, specifically for building static sites using VueJS. You should check it out to decide if it fits your needs. But this is out of scope for my series and I will not be discussing the differences or its features in this series.

Now that we got that out-of-the way. Here’s what I have planned for this series:

  1. Why VueJS
  2. VueJS basics
  3. Components in a static site too
  4. Data-driven sites
  5. Static sites and Functions

Why VueJS?

Why not abc, or xyz, or <insert framework here>?

For a small site that sees little traffic, with not a lot of functionality, I couldn’t justify wanting to use a heavier framework such as Angular or React. I realize React isn’t a framework but a library. In fact, VueJS borrows concepts from both of those technologies. The core team behind Vue has written this article to compare with other frameworks/libraries. I realize that I cannot do justice to every single framework out there. So let me put this out there. If you feel that I have not mentioned a framework that you are using, feel free to comment on this post and I’ll be happy to explore it. I love learning new things.

You should decide the best technology for yourself (or your team) based on what you think works for you, and the problem that you are solving. I am not recommending that you use VueJS for everything, but you should carefully evaluate them and understand why they exist. Here are some pointers for choosing a technology for your next project:

  • Do you already know how to use it?
  • Have you evaluated other frameworks with a small proof-of-concept?
  • How much time did it take to build the proof-of-concept?
  • Can you come up with a reason (or several reasons) as to why you should not use a particular technology?
  • Does the rest of your team know how to use it?
  • Does the

I spent a lot of time looking at a class of micro-frameworks. I even built the first version of the site using nothing but just plain HTML and used Parcel as my build tool. It worked great to start-off. But I quickly found myself wanting to do things outside of the boundaries of Parcel. Instead of fighting the framework, I made the decision to spend the time and switch to something else. As an alternative, I looked at Svelte, Stimulus, and even Hyperapp. These two are very different frameworks. I won’t go deep into how they work but they take a different approach to building web-apps than the big three (that I know), i.e., React, Angular, and Vue.

I had already used VueJS for a prior project. Although, that prior project was not a static site. It was a fully-dynamic web application and I loved using VueJS. Everything just fell into place when I used the framework. So with that good prior experience, I decided to use VueJS. I knew it will serve the purpose extremely well, and also have plenty of room for growth, should there be a need for it. Here’s why I enjoy using Vue:

  • Single-file components.
  • Component-scoped SCSS (although many frameworks offer this).
  • Automatic webpack build config (again, many frameworks offer this).
  • Easy-to-learn, (and re-learn when you are away from it for a long time) concepts.
  • Does not force some choices on you.
    • For example, there is no HTTP client available in Vue. The most popular one to use is axios. There is also vue-resource but, it has since been deprecated in favor of axios.
  • Easy bi-directional communication between parent and child components.

With that said, VueJS was an obvious next choice for me. Personally, I think VueJS could be used in a lot of situations but I understand that a variety of factors can influence one to choose another framework. So if you have any thoughts about it, I’d love to hear from you. Especially if VueJS hasn’t worked for you in some situation, I’d love to know why. It is good to know some of the bad things others may have experienced with Vue, when all I have had is a positive experience.

left-right

I created a new public repo on my GitHub page. Check it out.

UTC Offset regex validation

I was working on validating UTC Offset values in a javascript application and came up with this regex to do the job. What do you think?

//see http://en.wikipedia.org/wiki/List_of_UTC_time_offsets for list of valid positive and negative offsets
var positiveOffset = /^[+]?([0-9].?[0]?[0]?|1[0-4].?[0]?[0]?|[3,4,5,6,9,10,11].30|[5,8].45|12.45)$/g;
var negativeOffset = /^[-]([0-9].?[0]?[0]?|1[0-2].?[0]?[0]?|[3,4,9].30)$/g;
var GMT = /^0.?[0]?[0]?$/g;
if(!positiveOffset.test(value) && !negativeOffset.test(data.value) && !GMT.test(value)) {
    //show error
}

Closure function vs defined (named) function

I wrote a performance test on jsperf.com to measure the difference between calling a closure function from within a loop and calling a defined function within another loop for the same number of iterations. See the difference and run the test yourself.

PHP file download

So I have been working on a PHP website for a freelance job and had to write few lines of code to download a file from the database. Very simple right? Yeah that’s what I thought too. I mean it was < than 20 lines of code. Why wouldn’t it work? What could go wrong? That’s where I was wrong. This is what I had at first:

if(isset($_GET['id']))
{
  // if id is set then get the file with the id from database
  $id = $_GET['id'];
  $application = new Applications();
  $application->get($id);
  header("Content-length: $application->size");
  header("Content-type: $application->type");
  header("Content-Disposition: attachment; filename=$application->name");
  $content = $application->data;
  echo $content;
}
exit;

The problem I experienced was that a file would upload (different piece of code) fine. I knew that because the size attributes match when the file is written to the db. When I actually try to download the file back from the db using the script above, the file gets corrupted. I had no idea why! The weird (but made sense later) part was that plaintext files were fine no matter how large they were. It was binary files like images, DOCs, PDFs etc. So, I scoured the internet searching for answers and finally came across one thread somewhere where there was a similar discussion from over a year ago and someone said that the file stream would get random whitespace characters when downloading the file. Then it hit me, I remember seeing whitespace at the beginning of the stream when I had opened the corrupt file using notepad. The solution was to ob_clean() before you begin writing the headers and the content stream itself. You see one of the important points about writing header information to the client is that there shouldn’t be any whitespace before writing headers.

I modified the above code then to this:

if(isset($_GET['id']))
{
  // if id is set then get the file with the id from database
  $id = $_GET['id'];
  $application = new Applications();
  $application->get($id);
  ob_clean(); //clears output buffer in php..see php manual
  header("Content-length: $application->size");
  header("Content-type: $application->type");
  header("Content-Disposition: attachment; filename=$application->name");
  $content = $application->data;
  echo $content;
}
exit;

It would then download without any problems. At this time I should also caution you about dangling newline/whitespace in the php file itself which handles the download. The reason why plaintext files were ok is because plaintext files are not written in binary so whitespace or not it doesn’t matter for those file types and they will upload/download fine, at least in my case they did. Do you have a better way to handle this? If so, please leave a comment. Let me know about it.

canvas-charts

I just committed my first open source project on GitHub. You check it out here.

Here’s the example client with graphs:

Horizontal Bar Graph

 

Line graph

Simple validation of required fields in html5 mobile apps

I am working on an html5 mobile app and wanted a simple validation of required fields. Nothing fancy. Just a simple validation that would let the user know they left something blank. Since I was not interested in checking the format of the values entered in these fields, I felt that I should create something very generic that can be reused across platforms especially by using html5 features. A micro validation script, if I may.

So the setup is pretty easy. You need to mark your required input tags with the required attribute. Now, remember that this is an html5 attribute, so while older browsers won’t understand this it shouldn’t break anything. The next, optional, attribute to set is the data-tab-id, which when set tells validating function that it needs to mark that tab with an indication that it contains errors. This will be useful when you have data entry in multiple tabs.

<input id=”name” type=”text” placeholder=”name” maxlength=”25″ required=”required” data-tab-id=”#tab1″/>

Next is the CSS, simple, nothing extreme:

input.inputrequired{
border: 1px solid #ff0000;
}

a.haserrors{
color: #ff0000;
font-weight: bold;
}

The haserrors class is for the tab. You can change the selector for this class to match whatever tag you would have used with your tabs. Again, this is optional, you do not need to set the data-tab-id in the first place, if don’t need this and you will, in a moment, see why.

Finally, the script:

var _validateInput = function(e){
var currentTarget = e.currentTarget;
var tabId = currentTarget.dataset[“tabId”];
var tab = $(tabId);
var result = false;
if(currentTarget.required && currentTarget.value == “” && tab != null && typeof tab !== “undefined”){
$(“#” + currentTarget.id).css(“class”, “inputrequired”);
tab.addClass(“haserrors”);
}
else {
currentTarget.setAttribute(“class”, “”);
//before removing the haserrors from the tab class check if any other siblings are in error
if($(“#” + currentTarget.id).siblings(“.inputrequired”).length <= 0 && tab != null && typeof tab !== “undefined”){
tab.removeClass(“haserrors”);
}
//set result to true since this input is fine
result = true;
}
tab = null;
currentTarget = null;
return result;
};

The actual event trigger:

//validates onblur the inputs that have required attribute
$(“input”).on(“blur”, function(e){
validateInput(e);
}, false);

Although the required attribute is backward compatible, meaning no existing functionality would break, there is no need to worry about old browsers for mobile anyway. The data- attributes are an html5 addition as well. They won’t be recognized by older browsers and you cannot access the DOM string map dataset from an element in older browsers. And again, there is no need to worry about these things unless you are planning to use this for the desktop in which case you will need to replace the use of dataset with a JS framework’s data() method which provides cross-browser support.

One nice thing about the “required” attribute is that when you place fields with required attributes inside a <form> element, when the form is submitted, the browser automatically validates them and shows a nice tooltip that the a value is required for the element. I wrote this script because I wasn’t using a <form> element and don’t think the required attribute validation is supported in mobile webview at least it is not widely supported.

Optimizing HTML5 canvas drawing for high density screen

 //set the canvas size

canvasEl.style.width = this.containerWidth + “px”;

canvasEl.style.height = this.containerHeight + “px”;

// scale 2x

if(window.devicePixelRatio == 2) {

//set the actual drawing size

canvasEl.width = this.containerWidth * 2;

canvasEl.height = this.containerHeight * 2;

context.scale(2, 2);

}

On a side note, for PNGs you would do it with CSS3 media query: 

@media screen and (-webkit-min-device-pixel-ratio: 2), screen and (max–moz-device-pixel-ratio: 2) {

.your_class_name_here{

background: url(‘path_to_your_image_with_326ppi_here.png’);

width: 150px; //this is the size you actually want to scale it down to.

height: 150px; //this is the size you actually want to scale it down to.

}

}

More related articles:

http://menacingcloud.com/?c=highPixelDensityDisplays

http://blog.iwalt.com/2010/08/generating-highresolution-graphics-with-html5s-canvas-element.html