Categories
JavaScript Vue

Vue.js Basics — The Vue Instance

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look more closely at the Vue instance, including how to define it and some properties of it.

Characteristics of the Vue Instance

Each Vue.js app begins by defining a new Vue instance. The Vue constructor takes an options object that takes various properties.

We often use vm to refer to a Vue instance, where vm stands for ViewModel.

A Vue app roughly follows the Model-View-ViewModel pattern, where the ViewModel has the business logic of the app, View has the markup that users see, and Model has the data.

For example, we can define a Vue instance as follows:

const vm = new Vue({ });

Each Vue app consists of a root Vue instance and it’s created with new Vue . We can organize it in a tree for easier maintenance.

Data and Methods

The options object that pass into the Vue constructor can have data and methods.

For example, if we define a Vue instance as follows:

const vm = new Vue({  
  el: "#app",  
  data: { foo: "bar" }  
});

Then when we add:

console.log(vm.foo);

below our vm definition, we get 'bar' since data.foo has the value 'bar' .

In other words, if we have:

const data = { foo: "bar" };  
const vm = new Vue({  
  el: "#app",  
  data  
});  
console.log(vm.foo === data.foo);

Then the console.log will log true .

When the data changes, the app will re-render with the new data.

If we create a new property in vm and set it as follows:

let data = { foo: "bar" };  
const vm = new Vue({  
  el: "#app",  
  data  
});  
vm.a = 1;

The app won’t re-render. On the other hand, if we write:

let data = { foo: "bar", a: 1 };  
const vm = new Vue({  
  el: "#app",  
  data  
});

Then the app will re-render. This means that we have to put our data that we want to render in the data field.

If we freeze the object that we pass to data with Object.freeze() , then the Vue app won’t re-render since properties can’t be changed, so new changes can’t propagate since they aren’t set in the object.

So if we have:

let data = { foo: "bar", a: 1 };  
Object.freeze(data);  
const vm = new Vue({  
  el: "#app",  
  data  
});

No changes can be made after the initial render since we froze data with Object.freeze .

The Vue instance also exposes a number of instance properties and methods.

They’re prefixed with the $ so that we know they’re part of the Vue instance.

$el

We have the $el property to get the DOM element that the Vue instance resides in.

For example, if we have:

let data = { foo: "bar" };  
const vm = new Vue({  
  el: "#app",  
  data  
});

console.log(vm.$el === document.getElementById("app"));

Then the console.log will log true since our Vue instance resides in an element with ID app .

$data

The $data property will get us the value of the data property that we set in the options object that we passed into the Vue constructor.

So if we have:

let data = { foo: "bar" };  
const vm = new Vue({  
  el: "#app",  
  data  
});

console.log(vm.$data === data);

Then we get true from the console.log since data references the same object as vm.$data since we set it as the value of the data property of the options object that we passed into the Vue constructor.

$watch

$watch is an instance method that lets us watch for changes in the data object that we set as the value of the options object.

For example, if we have:

let data = { foo: "bar" };  
const vm = new Vue({  
  el: "#app",  
  data  
});

vm.$watch("foo", (newValue, oldValue) => {  
  console.log(newValue, oldValue);  
});

in src/index.js and:

<!DOCTYPE html>  
<html>  
  <head>  
    <title>Hello</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <input type="text" v-model="foo" />  
    </div>  
    <script src="./src/index.js"></script>  
  </body>  
</html>

in index.html . Then when we type in something to the input box, we should get some console.log output from:

vm.$watch("foo", (newValue, oldValue) => {  
  console.log(newValue, oldValue);  
});

This is because changes are constantly being watched in the data.foo property. v-model automatically updates the value for foo as we type into the box.

So as we’re typing, the changes to foo are being watched and it’s logged by the handler function that we passed into the $watch method.

Conclusion

The Vue instance is created by passing in an options object with the data , el , and methods properties to the Vue constructor. It returns an instance of our Vue app.

The instance has the $el property to get the DOM element that our app resides in.

Also, there’s the $data property to get the value of the data property to get the data that we set when we pass it in as the value of the data property of the options object.

Finally, we have the $watch method to watch for changes in our data.

Categories
JavaScript Nodejs

How To Build a Reverse Proxy With Express

If you use microservices architecture for your distributed system, there is a need for an API gateway. One good way to build an API gateway is to use a reverse proxy. Node.js is good for a reverse proxy because it’s fast and has lots of libraries to make a reverse proxy.

Express is the most popular framework for building web apps. It’s also very good for building a reverse proxy because there are add-ons to Express that can do the routing for the reverse proxy.

The design will be very simple. It will only redirect traffic to our different back-end apps according to the URL of the request. Also, it has to be able to pass header data, files, and cookies into our services in addition to the request payload.

To do all this, we first scaffold our app by running the Express application generator by following the instructions at https://expressjs.com/en/starter/generator.html

We have to run npx express-generator to generate the code that we need.

I suggest using nodemon to run our app in a development environment so that it restarts whenever our code changes.

Next, we have to install some packages to do the reverse proxy function and to enable CORS so that front end apps can use the reverse proxy. To do this, run npm i express-http-proxy glob node-env-file cookie-parser babel-register body-parser .

express-http-proxy is the HTTP reverse proxy library. cors is an add-on for Express that enables CORS. cookie-parser is an add-on allows Express to parse cookies. babel-register allows us to use the latest JavaScript features. node-env-file allows us to use .env file for storing environment variables. body-parser will be used to check for multipart requests. Multipart requests are requests that have files. The requests with files will not go through body-parser before redirecting.

Now we are ready to write code. We make a new file called helper.js in the helpers folder that we create.

In there, we add:

module.exports = {  
    isMultipartRequest: (req) => {  
        let contentTypeHeader = req.headers['content-type'];  
        return contentTypeHeader && contentTypeHeader.indexOf('multipart') > -1;  
    }  
}

This function checks for multipart requests, which are requests that are sent in as form data. It can include text or files.

In app.js , we write:

require("babel-register");  
let express = require('express');  
let cors = require('cors')  
let config = require('./config/config');  
let env = require('node-env-file');  
let helpers = require('./app/helpers/helpers');  
let bodyParser = require('body-parser');  
env(__dirname + '/.env');
let app = express();

app.use(cors({  
  credentials: true,  
  origin: true  
}));

const bodyParserJsonMiddleware = function () {  
  return function (req, res, next) {  
    if (helpers.isMultipartRequest(req)) {  
      return next();  
    }  
    return bodyParser.json()(req, res, next);  
  };  
};

app.use(bodyParserJsonMiddleware());

app.all('*', (req, res, next) => {  
  let origin = req.get('origin');  
  res.header('Access-Control-Allow-Origin', origin);  
  res.header("Access-Control-Allow-Headers", "X-Requested-With");  
  res.header('Access-Control-Allow-Headers', 'Content-Type');  
  next();  
});

module.exports = require('./config/express')(app, config);

app.listen(config.port, () => {  
  console.log('Express server listening on port ' + config.port);  
});

The code works by passing on server-side cookies and allows multipart requests to not pass through body-parser since it is not JSON.

Also, we allow CORS in the block below:

app.all('*', (req, res, next) => {  
  let origin = req.get('origin');  
  res.header('Access-Control-Allow-Origin', origin);  
  res.header("Access-Control-Allow-Headers", "X-Requested-With");  
  res.header('Access-Control-Allow-Headers', 'Content-Type');  
  next();  
});

It allows requests from all origins to be accepted. By default, only requests from the same host as the back end are accepted since it is insecure to allow requests from other hosts. However, if we allow mobile and standalone front-end web apps to make requests through our reverse proxy, we have to allow all origins. It gets the origin from the header and allows the request from that origin to proceed.

Then we add the code for proxying requests in controllers/home.js:

const express = require('express');  
let proxy = require("express-http-proxy");  
let helpers = require('../helpers/helpers');
let loginAppRoutes =[  
  '/login*',  
  '/loginms',  
  '/register',  
  '/resetPassword',  
  '/getActivationKey*',  
  '/activateAccount',  
  '/logout',  
  '/reports',  
  '/'  
]

let uploadRoutes = [  
  '/uploadlogo*',  
]

module.exports = (app) => {  
  const proxyMiddleware = () => {  
    return (req, res, next) => {  
      let reqAsBuffer = false;  
      let reqBodyEncoding = true;  
      let contentTypeHeader = req.headers['content-type'];  
      if (helpers.isMultipartRequest(req)) {  
        reqAsBuffer = true;  
        reqBodyEncoding = null;  
      }  
      return proxy(process.env.UPLOAD_URL, {  
        reqAsBuffer: reqAsBuffer,  
        reqBodyEncoding: reqBodyEncoding,  
        parseReqBody: false,  
        proxyReqOptDecorator: (proxyReq) => {  
          return proxyReq;  
        }, 

        proxyReqPathResolver: (req) => {  
          return `${process.env.UPLOAD_APP_URL}/${req.baseUrl}${req.url.slice(1)}`;  
        }, 

        userResDecorator: (rsp, data, req, res) => {  
          res.set('Access-Control-Allow-Origin', req.headers.origin);  
          return data.toString('utf-8');  
        }  
      })(req, res, next);  
    };  
  } 

  uploadRoutes.forEach(r => {  
    app.use(r, proxyMiddleware());  
  }) 

  loginAppRoutes.forEach(r => {  
    app.use(r, proxy(process.env.LOGIN_URL, {  
      proxyReqOptDecorator: (proxyReq) => {  
        return proxyReq;  
      },

      proxyReqPathResolver: (req) => {  
        return `${process.env.LOGIN_URL}/${req.baseUrl}${req.url.slice(1)}`;  
      }, 

      userResDecorator: (rsp, data, req, res) => {  
        res.set('Access-Control-Allow-Origin', req.headers.origin);  
        return data.toString('utf-8');  
      }  
    }));  
  })  
};

We check for multipart form requests with:

if (helpers.isMultipartRequest(req)) {  
  reqAsBuffer = true;  
  reqBodyEncoding = null;  
}

The will pass requests with files straight through to our internal APIs.

The following:

proxyReqPathResolver: (req) => {  
  return `${process.env.LOGIN_URL}/${req.baseUrl}${req.url.slice(1)}`;  
},

is where the actual redirect URL from the proxy to internal API is set. Note that parseReqBody is false , so that multipart form requests are not parsed as JSON.

The process.env variables are set in the .env file.

In the .env file, we have:

LOGIN_URL='http://urlForYourLoginApp'  
UPLOAD_URL='http://anotherUrlForYourUploadApp'

With reverse proxy add-on, Express is one of the best choices for building a reverse proxy in Node.

Categories
JavaScript Vue

Basic Vue Form Validation with VeeValidate

Form validation is a common requirement of in most web apps. This is no different with Vue apps.

Vue doesn’t provide a solution for form validation out of the box. Therefore, we have to find our own solution for form validation.

In this article, we’ll look at how to do basic Vue form validation with VeeValidate.

Getting Started

We can get started by including the VeeValidate library by writing:

<script src="https://unpkg.com/vee-validate@latest"></script>

in our HTML file.

Then we can write:

Vue.component("validation-provider", VeeValidate.ValidationProvider);

to include the validation-provider component in our app. We need to wrap this around our form fields to let VeeValidate do validation on it.

Then we need to define some form validation rules to actually do the form validation.

To do this, we use the VeeValidate.extend function, which takes the rule name string as the first argument, and the callback function that returns the condition for a validate input as the second argument.

For instance, we can use Veelidate.extend as follows to create a rule for for validating that the inputted value is an odd number:

VeeValidate.extend("odd", value => {
  return value % 2 !== 0;
});

In the code above, we check if value % 2 returns 0 or not. If it doesn’t then it’s an odd number.

Likewise, we can do something similar to check if an inputted value is a positive number as follows:

VeeValidate.extend("positive", value => {
  return value >= 0;
});

We can use the rules as follows in a small app with a form field that we can enter something into:

index.js:

Vue.component("validation-provider", VeeValidate.ValidationProvider);

VeeValidate.extend("odd", value => {
  return value % 2 !== 0;
});

VeeValidate.extend("positive", value => {
  return value >= 0;
});
new Vue({
  el: "#app",
  data: {
    value: ""
  }
});

index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vee-validate@latest"></script>
  </head>
  <body>
    <div id="app">
      <validation-provider rules="positive|odd" v-slot="{ errors }">
        <input v-model="value" type="text" name="value" />
        <span>{{ errors[0] }}</span>
      </validation-provider>
    </div>
    <script src="index.js"></script>
  </body>
</html>

In the template above, we have a slot that gets the errors object from the validation-provider component which contains the form validation errors messages.

We display the first one by accessing the string on the 0 index of errors.

The rules prop has the rules separated by the | symbol. We applied the positive and odd rules that we defined earlier in index.js

Note that the validation-provider is wrapped around our input. This is required to validate the input. We wrap one validation-provider per input.

Then when type in something that’s not a positive, odd number, we’ll see ‘value is not valid’ displayed.

value is from the value of the name attribute of the input.

Rule Arguments

We can pass in arguments to rule callbacks so that we can do more complex validations. For instance, we can write the following rule to validate that the inputted value is a number bigger than or equal to a certain number:

VeeValidate.extend("min", {
  validate(value, args) {
    return value >= args.num;
  },
  params: ["num"]
});

Then we can apply it as follows:

index.js:

Vue.component("validation-provider", VeeValidate.ValidationProvider);

VeeValidate.extend("min", {
  validate(value, args) {
    return value >= args.num;
  },
  params: ["num"]
});

new Vue({
  el: "#app",
  data: {
    value: ""
  }
});

index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vee-validate@latest"></script>
  </head>
  <body>
    <div id="app">
      <validation-provider rules="min:5" v-slot="{ errors }">
        <input v-model="value" type="text" name="value" />
        <span>{{ errors[0] }}</span>
      </validation-provider>
    </div>
    <script src="index.js"></script>
  </body>
</html>

In the code above, we have min:5 to indicate that we want to make sure that our inputted value is 5 or greater.

Conclusion

Validation of Vue forms with VeeValidate is simple. We can do a lot with a few lines of code.

Validation rules are defined with extend. And we use the validation-provider component to validate inputs by wrapping it around the input element.

Also, we can pass in arguments to validation rules to make them more flexible.

Categories
JavaScript

More JavaScript Mistakes You May be Making

JavaScript is a language that’s friendlier than many other programming languages in the world. However, it’s still very easy to make mistakes when writing JavaScript code through misunderstanding or overlooking stuff that we already know. By avoiding some of the mistakes below, we can make our lives easier by preventing bugs and typos in our code that bog us down with unexpected results.


Confusing Undefined and Null

JavaScript has both undefined and null for non-values. However, there are quite a few differences between the two. undefined means that the variable may have been declared, but nothing is set to it. A variable can also be explicitly set as undefined. The type of an undefined variable, when checking the type with the typeof operator, will get us the type 'undefined'. Functions that don’t return anything returns undefined. On the other hand, null values have to be explicitly set by functions that return null or just set directly to a variable. When we check an object that has the null value set, we’ll find that the type of it is'object' if a variable has the null value.

For this reason, it’s probably easier to stick to undefined whenever we can when we’re setting variable values to non-values. It reduces confusion and we only have to check that the type of a variable is 'undefined' to see whether it’s undefined. That’s less painful than having two checks, for both null and undefined.

To write functions that return undefined, we don’t have to do anything like the following example:

const f = () => {}

To set a variable that was assigned some other value to undefined, we can write:

x = undefined;

To check if a property value is undefine, we can write:

typeof obj.prop === 'undefined'

or

obj.prop === undefined

To check if a variable is undefined, we can write the following code:

typeof x === 'undefined'

A declared variable that hasn’t been assigned anything automatically has the value undefined.

If we have to check for null, then we can write:

obj.prop === null

or

x === null

for variables. We can’t use the typeof operator for checking null because the data type of null is 'object'.

<img class="do t u hm ak" src="https://miro.medium.com/max/10084/0*79d0pk1RCiMWq6dC" width="5042" height="3151" role="presentation"/>

Photo by Mikhail Vasilyev on Unsplash


Confusing Addition and Concatenation

In JavaScript, the + operator is used for both adding two numbers and concatenating strings together. Because JavaScript is a dynamic language, the operands are all automatically converted to the same type before the operation is applied. For example, if we have:

let x = 1 + 1;

then we get two because they’re both numbers. The + operation was used for addition like we expected. However, if we have the following expression:

let x = 1 + '1';

then we get '11' because the first operand was coerced into a string before the + operation is applied. The + operation was used for concatenation instead of addition. When we use the + operator on multiple variables, this makes knowing the type even harder. For example, if we have:

let x = 1;  
let y = 2;  
let z = x + y;

as we expect, we get three because x and y are both numbers. On the other hand, if we have:

let x = 1;  
let y = '2';  
let z = x + y;

then we get '12' because y is a string, so the + operator was used for concatenation instead. To solve this issue, we should convert all the operands to numbers first before using them with the + operator. For example, we should rewrite the above example into the following:

let x = 1;  
let y = '2';  
let z = Number(x) + Number(y);

The code above will get us 3 as the value of z since we converted them both to numbers with the Number factory function first. The Number function takes in any object and returns a number if it can be parsed into a number, or NaN otherwise. An alternative way to do this is to use the new Number(...).valueOf() function, as we do in the following code:

let x = 1;  
let y = '2';  
let z = new Number(x).valueOf() + new Number(y).valueOf();

Since new Number(...) is a constructor that creates an object type, we want to use the valueOf function to convert it back to a primitive type to make sure that what we get is a number type. A shorter way to do this is to write:

let x = 1;  
let y = '2';  
let z = +x + +y;

The + sign in front of a single operand will try to convert the single operand into a number or toNaN if it can’t be converted into a number. It does the same thing as the Number function. We can also convert a variable to a particular type of number. The Number object has a parseInt function to convert a string or object into an integer and a parseFloat function to convert a string or object into a floating-point number. parseInt takes the object you want to convert to a number as the first argument. It also takes a radix as an optional second argument, which is the base of the mathematical numeral systems. If the string starts with 0x, then the radix will be set to 16. If the string starts with anything else, then the radix will be set to 10.

We can use them as in the following examples:

let x = 1;  
let y = '2';  
let z = Number.parseInt(x) + Number.parseInt(y)

Also, we can use the parseFloat function as in the following code:

let x = 1;  
let y = '2';  
let z = Number.parseFloat(x) + Number.parseFloat(y)

We will get 3 in both of the examples above.


Breaking Return Statements Into Multiple Lines

JavaScript closes a statement at the end, so one line code is considered distinct from the other. For example, if we have:

const add = (a, b) => {  
  return  
  a + b;  
}

we get undefined if we run console.log(add(1, 2)); since we ran the return statement, which ended the function execution, before a + b is run. Therefore, a + b will never be run in this function. To fix this, we either have to put the return statement all in one line or use parentheses to surround what we want to return. For example, we can write:

const add = (a, b) => {  
  return a + b;  
}

This will log 3 if we run console.log(add(1, 2)); since we are actually returning the computed result in the function. We can also write:

const add = (a, b) => {  
  return (  
    a + b  
  );  
}

This is handy for returning expressions that might be longer than one line. This will also log 3 if we run console.log(add(1, 2));. For arrow functions, we can also write:

const add = (a, b) => a + b

for single-line functions since the return statement is implicit for single-line arrow functions. We can also write:

const add = (a, b) => (a + b)

to get the same thing. This also works for single-line arrow functions.

In JavaScript, if a statement is incomplete, like the first line of:

const power = (a) => {  
  const  
    power = 10;  
  return a ** 10;  
}

inside the function then the JavaScript interpreter will run the first line together with the second line to get the full statement. So:

const  
  power = 10;

is the same as:

const power = 10;

However, for complete statements like return statements, the JavaScript interpreter will treat them as separate lines. So:

return   
  a ** 10;

is not the same as:

return a ** 10;

Even though JavaScript is a friendly language, it’s still very easy to make mistakes when writing JavaScript code. It’s easy to confuse undefined and null when we aren’t familiar with JavaScript. Because of the dynamic typing nature of JavaScript, operators like the + operator that can do multiple things can easily be converted to a type we don’t expect and produce the wrong result. Also, if statements can be complete on their own, then they shouldn’t be written in their own lines if we want both lines to be together.

Categories
Python

Quick Intro to Python Loops

Python is a convenient language that’s often used for scripting, data science, and web development.

In this article, we’ll look at various kinds of loops that we can use in Python apps to run repeated code.

while Loop Statements

We can use the while loop to run code repeatedly while a condition is True .

It consists of the while keyword, a condition to evaluate, a colon, and then the code to run indented below it.

For example, we can write the following while loop to print a message repeatedly:

x = 0  
while x < 5:  
    print('Hello.')  
    x = x + 1

In the code above, we have x set to 0. Then we use the while loop to print ‘Hello.’. Next, we increment x by 1. We do this repeatedly until x reaches 5.

while loops are useful for looping keeping the loop running until we meet a condition. It doesn’t have to have a finite, determinate amount of iterations.

For example, we can use the while loop until the user guesses the right number as follows:

guess = 0  
while int(guess) != 5:  
  print('Guess a number')  
  guess = input()  
print('You got it')

In the code above, as long as guess doesn’t evaluate to 5 when we convert it to an integer, the while loop will keep running.

Once we entered the right guess, which is 5, the loop will end.

break Statements

The break keyword is used to terminate a loop before the loop ends.

For example, we can rewrite the example above, with break instead of the condition in the while loop as follows:

guess = 0  
while True:  
  if int(guess) == 5:  
    break  
  print('Guess a number')  
  guess = input()  
print('You got it')

In the code above, we have an infinite while loop that has the condition to end the loop with break when we int(guess) returns 5.

The rest of the code works the same way as before.

continue Statements

We can use the continue statement to move on to the next iteration of the loop.

For example, we can use it as follows:

x = 0  
while x < 5:  
  x = x + 1  
  if x == 2:  
    continue  
  print(x)

The code above prints the value of x if it’s not 2. This is because if x is 2, we run continue to skip to the next iteration.

Truthy and Falsy Values

Python has the concept of truthy and falsy values. Truthy values are automatically converted to True when we use them where we have condition checks.

Falsy values are converted to False when we use them for condition checks.

0, 0.0, and '' (the empty string) are all considered False , while all other values are considered True .

For example, we can write a program to prompt users to enter a name and won’t stop until they enter one as follows:

name = ''  
while not name:  
  print('Enter your name:')  
  name = input()  
print('Your name is', name)

In the code above, we use not name to check if name is an empty string or not. If it is, then we keep showing 'Enter your name.' until they enter one.

Once they did, we display the last line with the name .

for Loops and the range() Function

We can use the for loop to loop through a certain number of items.

For example, we can use the for loop with the range function to display numbers from 0 to 4 as follows:

for i in range(5):  
    print(i)

In the code above, the range function returns integers starting from 0 as we and increments the number as we loop up to the number passed into the range function minus 1.

As we can see, the for loop consists of the for keyword, a variable name, the in keyword, a call to the range function, a colon , and then the block of code to run in the loop.

We can also use break and continue statement inside for loops as we did in while loops.

The range function can take 3 arguments, where the first is the starting number and the 2nd argument is the ending number. The loop will terminate when it reaches the ending number minus 1.

The 3rd argument is the increment to increase the variable by in each iteration.

For example, we can write the following code to print all odd numbers between 1 and 10:

for i in range(1, 10, 2):  
    print(i)

We should see:

1  
3  
5  
7  
9

printed because in our range function call, we passed in 1 as the starting number, 10 as the ending number, and 2 to increment i by 2 in each iteration.

Conclusion

We can use while loops to repeatedly run a block of code until a condition is met. This means the loop can run an indeterminate number of iterations.

break is used for ending a loop before it ends. continue is used to skip the loop to the next iteration.

for loops are used for repeatedly run code a finite number of times. It’s used with the range function to do the finite iteration.