Categories
JavaScript

Add Charts to Our JavaScript App with Anychart

Anychart is an easy to use library that lets us add chart into our JavaScript web app.

In this article, we’ll look at how to create basic charts with Anychart.

Create Our First Chart

We can create our first chart by adding the script tag to add the Anychart library:

<script src="https://cdn.anychart.com/releases/8.9.0/js/anychart-base.min.js" type="text/javascript"></script>

Then we add a container element for the chart:

<div id="container" style="width: 500px; height: 400px;"></div>

We set the id which we’ll use later.

Then to create a pie chart, we write:

anychart.onDocumentLoad(() => {
   const chart = anychart.pie();
   chart.data([
     ["apple", 5],
     ["orange", 2],
     ["grape", 2],
   ]);
   chart.title("Most popular fruits");
   chart.container("container");
   chart.draw();
 });

We create a pie chart with anychart.pie() .

Then we call chart.data to add our data in an array.

chart.title sets the chart title.

chart.container sets the ID of the container to render the chart in.

chart.draw draws the chart.

Load Data from XML

We can load data from XML.

For instance, we can write the following HTML:

<div id="container" style="width: 500px; height: 400px;"></div>

And the following JavaScript code:

const xmlString = `
<xml>
 <chart type="pie" >
  <data>
   <point name="apple" value="1222"/>
   <point name="orange" value="2431"/>
   <point name="grape" value="3624"/>
  </data>
 </chart>
</xml>
`

anychart.onDocumentLoad(() => {
  const chart = anychart.fromXml(xmlString);
  chart.title("Most popular fruits");
  chart.container("container");
  chart.draw();
});

to add a pie chart that renders the given XML string.

We have the chart tag with the type attribute set to 'pie' .

The data tag has the point elements which have the data.

name has the keys and value has the value.

Load Data from JSON

To load data from JSON objects, we can use the anychart.fromJSON method.

We keep the same HTML as before, and we write the following JavaScript:

const json = {
  "chart": {
    "type": "pie",
    "data": [
      ["apple", 1222],
      ["orange", 2431],
      ["grape", 3624],
    ]
  }
};

anychart.onDocumentLoad(() => {
  const chart = anychart.fromJson(json);
  chart.title("Most popular fruits");
  chart.container("container");
  chart.draw();
});

We have the json object with the chart property that has the chart data.

type has the chart type to render.

data has an array of key-value arrays with the data.

Load Data from CSV

We can load chart data from CSV with the chart.title method.

For instance, we can write:

const csvString = `
  2009-02-06,6764n
  2009-02-07,7056n
  2009-02-08,7180n
`

anychart.onDocumentLoad(() => {
  const chart = anychart.area();
  chart.area(csvString);
  chart.title("Profit growth");
  chart.container("container");
  chart.draw();
});

We have the csvString variable that has a string with the CSV columns.

The first is the x-axis values.

The 2nd column is the y-axis values.

Then we pass csvString to chart.area to use csvString ‘s data to render our area chart.

Conclusion

We can render charts from various data sources easily with Anychart.

Categories
Vue

Developing Vue Apps with Class-Based Components — Type Annotations

If we prefer to use classes, we can use the class-based components API that comes with Vue.

In this article, we’ll look at how to developing Vue apps with class-based components.

TypeScript Autocomplete for External Hooks

We can add autocomplete for external hooks within our class-based components written in TypeScript.

For instance, we can write:

vue-router-hook-types.ts

import Vue from "vue";
import { Route, RawLocation } from "vue-router";

declare module "vue/types/vue" {
  interface Vue {
    beforeRouteEnter?(
      to: Route,
      from: Route,
      next: (to?: RawLocation | false | ((vm: Vue) => void)) => void
    ): void;

    beforeRouteLeave?(
      to: Route,
      from: Route,
      next: (to?: RawLocation | false | ((vm: Vue) => void)) => void
    ): void;

    beforeRouteUpdate?(
      to: Route,
      from: Route,
      next: (to?: RawLocation | false | ((vm: Vue) => void)) => void
    ): void;
  }
}

main.ts

import Vue from "vue";
import App from "./App.vue";
import Foo from "./views/Foo.vue";
import Bar from "./views/Bar.vue";
import VueRouter from "vue-router";
import "./vue-router-hook-types";
Vue.config.productionTip = false;
const routes = [
  { path: "/foo", component: Foo },
  { path: "/bar", component: Bar }
];
const router = new VueRouter({
  routes
});
Vue.use(VueRouter);
new Vue({
  router,
  render: (h) => h(App)
}).$mount("#app");

App.vue

<template>
  <div id="app">
    <router-link to="/foo">Foo</router-link>
    <router-link to="/bar">Bar</router-link>
    <router-view></router-view>
  </div>
</template>
<script>
export default {
  name: "App",
};
</script>

views/Bar.vue

<template>
  <div>bar</div>
</template>
<script>
import Vue from "vue";
import Component from "vue-class-component";
Component.registerHooks([
  "beforeRouteEnter",
  "beforeRouteLeave",
  "beforeRouteUpdate",
]);
@Component
export default class Foo extends Vue {
  beforeRouteEnter(to, from, next) {
    console.log("beforeRouteEnter");
    next();
  }
  beforeRouteUpdate(to, from, next) {
    console.log("beforeRouteUpdate");
    next();
  }
  beforeRouteLeave(to, from, next) {
    console.log("beforeRouteLeave");
    next();
  }
}
</script>

views/Foo.vue

<template>
  <div>foo</div>
</template>
<script>
import Vue from "vue";
import Component from "vue-class-component";
import "vue-class-component/hooks";

Component.registerHooks([
  "beforeRouteEnter",
  "beforeRouteLeave",
  "beforeRouteUpdate",
]);
@Component
export default class Foo extends Vue {
  beforeRouteEnter(to, from, next) {
    console.log("beforeRouteEnter");
    next();
  }
  beforeRouteUpdate(to, from, next) {
    console.log("beforeRouteUpdate");
    next();
  }
  beforeRouteLeave(to, from, next) {
    console.log("beforeRouteLeave");
    next();
  }
}
</script>

We have the vue-router-hook-types.ts with the type definitions for the Vue Router hooks.

In main.ts , we have:

import "./vue-router-hook-types";

to import the type definitions.

Then in the Foo.vue and Bar.vue components, we can see the beforeRouteEnter, beforeRouteUpdate, and beforeRouteLeave hooks in the autocomplete menu when we’re typing them into the component class code.

We can also annotate types of methods in our code.

For instance, we can write:

<template>
  <div>
    <button @click="increment">increment</button>
    <p>{{ count }}</p>
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";

@Component(({
  watch: {
    count(val: number) {
      this.log(val)
    }
  }
})
export default class HelloWorld extends Vue {
  count: number = 0

  log(val: number): void {
    console.log(val)
  }

  increment(){
    this.count++
  }
}
</script>

We have the log method that returns void and takes a val parameter with type number ,

We use that in the count watcher which is defined in the argument we pass into Component .

This way, we won’t have to worry about passing parameters with data types we don’t expect.

And the same applies to return types of methods.

Conclusion

We can annotate data types easily with TypeScript to avoid making mistakes in our Vue class-based components.

Categories
Vue

Developing Vue Apps with Class-Based Components — TypeScript, Superclasses, Hooks, and Mixins

If we prefer to use classes, we can use the class-based components API that comes with Vue.

In this article, we’ll look at how to developing Vue apps with class-based components.

TypeScript, Superclasses, and Mixins

We can add props and inherit superclass components with the mixins method in our Vue TypeScript project.

For instance, we can write:

<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import Component, { mixins } from "vue-class-component";

const GreetingProps = Vue.extend({
  props: {
    name: String,
  },
});

@Component
class Super extends Vue {
  lastName = "smith";
}

@Component
export default class HelloWorld extends mixins(GreetingProps, Super) {
  get message(): string {
    return `Hello, ${this.name} ${this.lastName}`;
  }
}
</script>

We create the Super component class with the 1astName property.

And we have the GreetProps class that we create with the Vue.extend method so we can accept props in a way that’s acceptable by TypeScript.

Then we call the mixins method with the GreetProps and Super methods so we can inherit from both classes.

We inherit from both classes, so this.name is 'james' and this.lastName is 'smith' .

We can define properties with type definitions.

For instance, we can write:

<template>
  <div>
    <p v-for="p of persons" :key="p">{{ p.firstName }} {{ p.lastName }}</p>
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";

interface Person {
  firstName: string;
  lastName: string;
}

@Component
export default class HelloWorld extends Vue {
  persons!: Person[] = [
    { firstName: "james", lastName: "smith" },
    { firstName: "jane", lastName: "doe" },
  ];
}
</script>

We create the Person interface and use that for defining the type of the persons class property.

The ! means the class property isn’t nullable.

Now if the persons array entries have extra properties, we’ll get an error from the TypeScript compiler.

Refs and TypeScript

To define and assign refs with TypeScript class-based Vue components, we write:

<template>
  <div>
    <input ref="input" />
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";

@Component
export default class HelloWorld extends Vue {
  $refs!: {
    input: HTMLInputElement;
  };

  mounted() {
    this.$refs.input.focus();
  }
}
</script>

We have to set the type for each $refs property we assign.

input is an HTML input element, so we set it to the HTMLInputElement type.

Then we call call focus on it to focus it.

With the type annotation added, we get autocomplete when we type in the code in the mounted hook.

Hooks Autocomplete

To add autocomplete for hooks, we write:

main.ts

import Vue from "vue";
import App from "./App.vue";
import "vue-class-component/hooks";
Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App)
}).$mount("#app");

App.vue

<template>
  <div id="app">
    <HelloWorld />
  </div>
</template>

<script lang='ts'>
import HelloWorld from "./components/HelloWorld.vue";

export default {
  name: "App",
  components: {
    HelloWorld,
  },
};
</script>

components/HelloWorld.vue

<template>
  <div>
    {{ message }}
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";

@Component
export default class HelloWorld extends Vue {
  data() {
    return {
      message: "hello world",
    };
  }
}
</script>

Once we add:

import "vue-class-component/hooks";

in main.ts , we get autocomplete when we type in data in the HelloWorld component.

Conclusion

We can add hooks autocomplete, mixins and superclass inheritance, and refs type annotation within our Vue class-based components written in TypeScript.

Categories
Vue

Developing Vue Apps with Class-Based Components — Mixins and TypeScript

If we prefer to use classes, we can use the class-based components API that comes with Vue.

In this article, we’ll look at how to developing Vue apps with class-based components.

Mixins

We can create mixins for Vue class-based components with the mixins function.

For instance, we can write:

<template>
  <div>
    <p>{{ hello }} {{ world }}</p>
  </div>
</template>

<script>
import Vue from "vue";
import Component, { mixins } from "vue-class-component";

@Component
class Hello extends Vue {
  hello = "Hello";
}

@Component
class World extends Vue {
  world = "World";
}

@Component
export default class HelloWorld extends mixins(Hello, World) {
  created() {
    console.log(this.hello, this.world);
  }
}
</script>

We call mixins with the Hello and World class components.

Then the hello and world class properties will be accessible from the Helloworld component class.

To access them within the class, we can access them from the this object.

And we can also access them in the template.

this Value

We can’t use arrow functions as methods in our component class since we need to access this inside.

Arrow function doesn’t bind to this , so we cant’ use them as class methods.

For instance, if we write:

<template>
  <div>
    <p @click="bar">{{ foo }}</p>
  </div>
</template>

<script>
import Vue from "vue";
import Component from "vue-class-component";

@Component
export default class HelloWorld extends Vue {
  foo = 123;

  bar = () => {
    this.foo = 456;
  };
}
</script>

Then bar won’t update the value of foo since the value of this isn’t the class instance.

Constructor

We shouldn’t add constructor in our class components since they don’t fit with the Vue lifecycle.

For instance, we shouldn’t write:

<template>
  <div>
    <p>{{ foo }}</p>
  </div>
</template>

<script>
import Vue from "vue";
import Component from "vue-class-component";

@Component
export default class HelloWorld extends Vue {
  foo = 123;

  constructor() {
    this.foo = 456;
  }
}
</script>

We can’t access reactive properties in the constructor and we’ll get an error if we try in the constructor.

Creating Class Components with TypeScript

We can create class-based components with TypeScript.

For instance, we can write:

src/components/HelloWorld.vue

<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";

const GreetingProps = Vue.extend({
  props: {
    name: String,
  },
});

@Component
export default class HelloWorld extends GreetingProps {
  get message(): string {
    return `Hello, ${this.name}`;
  }
}
</script>

src/App.vue

<template>
  <div id="app">
    <HelloWorld name="james" />
  </div>
</template>

<script lang='ts'>
import HelloWorld from "./components/HelloWorld.vue";

export default {
  name: "App",
  components: {
    HelloWorld,
  },
};
</script>

tsconfig.json

{
  "compilerOptions": {
    "esModuleInterop": true
  }
}

We add the compilerOptions.esModuleInterop property and set it to true so that we can import ES modules in our code.

In App.vue , we register the HelloWorld component.

And in HelloWorld.vue , we call Vue.extend to create the GreetProps class with the props.

Then we can use the extends keyword to create a class that extends GreetingsProp to accept the name prop.

In the template, we display the message , which we get from the message getter.

Conclusion

We can use Vue class-based components with TypeScript and define mixin classes easily in our Vue project.

Categories
Vue

Developing Vue Apps with Class-Based Components — Custom Decorators and Superclass Component

If we prefer to use classes, we can use the class-based components API that comes with Vue.

In this article, we’ll look at how to developing Vue apps with class-based components.

Custom Decorators

We can add our own decorators into our Vue class-based components.

For instance, we can write:

<template>
  <div>
    <button @click="increment(2)">increment</button>
    <p>{{ count }}</p>
  </div>
</template>

<script>
import Vue from "vue";
import Component, { createDecorator } from "vue-class-component";

const Log = createDecorator((options, key) => {
  const originalMethod = options.methods[key];

  options.methods[key] = function wrapperMethod(...args) {
    console.log(`Invoked: ${key}(`, ...args, ")");
    originalMethod.apply(this, args);
  };
});

@Component
export default class HelloWorld extends Vue {
  count = 0;

  @Log
  increment(val) {
    this.count += val;
  }
}
</script>

We create the Log decorator with the createDecorator method.

We pass in a callback with the options and key parameter.

options has the items in the Vue class component.

key has the name of the properties in the Vue component class.

options.methods lets us access the methods.

Then we can override the method by assigning another function as its value.

Inside the wrappedMethod , we call originalMethod.apply to call the originalMethod with this being the component class instance.

args is the arguments we pass into the component method.

Since we pass in the 2 as the value of val into increment , that will be the value in the args array when we call increment

key is the 'increment' method name when we click on the button.

Extending a Component

One benefit of using a class-based component is that we can create a superclass component that has the shared parts we want to inherit.

For instance, we can write:

<template>
  <div>
    <p>{{ superValue }}</p>
  </div>
</template>

<script>
import Vue from "vue";
import Component from "vue-class-component";

@Component
class Super extends Vue {
  superValue = "Hello";
}

@Component
export default class HelloWorld extends Super {}
</script>

We have the Super component class that has the superValue property.

And we have the HelloWorld component class that extends the Super class.

HelloWorld has the superValue property inherited from Super , so we can use it in the template.

Also, we can access the value within the child component class.

For instance, we can write:

<template>
  <div>
    <p>{{ superValue }}</p>
  </div>
</template>

<script>
import Vue from "vue";
import Component from "vue-class-component";

@Component
class Super extends Vue {
  superValue = "Hello";
}

@Component
export default class HelloWorld extends Super {
  created() {
    console.log(this.superValue);
  }
}
</script>

We log the this.superValue property inherited from the Super class in the created hook.

And we should see 'Hello' logged.

Conclusion

We can add custom decorators and superclass components into our Vue app when we use class-based components.