Awesome Future of Frontend in 2020

Awesome Future of Frontend in 2020

Before we dive in to Future of Frontend in 2020. Let’s begin with some basics as we gradually get more forward-looking. We obviously cannot know what technology will dominate in 2020 and what framework will pop up. But we can try at least.

What is frontend?

Frontend is referred to as the pattern of transforming data to a graphical interface with the use of CSS, HTML, and JavaScript, so that users can easily view and efficiently interact with the data. It distinctively translates a computer programming source code into an intermediate illustration to produce code in a computer output language.

It is also a common term used by programmers and computer programmers to describe part of the layers that make up a website, computer program or hardware, which are depicted based on how accessible they are to a user. The frontend layer strategically placed on top of the backend includes all software or hardware that is part of a user interface.

Professionals such as web designers usually handle Frontend section of every project and the components are customer facing. Some of these components includes:

  • Search engine optimization (SEO)
  • Graphic design and image editing tools
  • Design and markup languages such as CSS and HTML
  • Web performance and browser compatibility
  • Usability and accessibility testing

Frontend Career

Frontend career is an interesting area with availability of various great remunerations as a profession that becomes easier with the adequate knowledge of the three primary coding languages i.e. CSS, HTML and JavaScript. Research has deducted that frontend development is and will always be a good career path for humans because software keeps evolving every day.

The consistent demands for frontend career specialist is very high. Some of the key skills of a frontend developer are responsive design, frameworks, debugging, web performance, CSS preprocessing and command line among others.

Consider taking our VueJS Certification or VueJS Online Course. It’s on-demand, easy to understand and has tremendous benefits for you career.

Relevant Areas of Frontend

An important area where frontend (client-side programming) is of high relevance is UI, UX. There is a distinct relationship between frontend, UI and UX. They work together seamlessly. The UX design centered on the satisfaction of the user experiences with software. Frontend development is the technical implementation of the software user interface.

UI design is the graphical bridge that connects the UX and frontend. An individual can choose to be a UI, UX, and frontend web developer in which he/she will be responsible for applying interactive and visual design experience. For you to be successful in this field, you must be able to observe users behavior to bring the best out of an application. Your primary aim should be to ensure user-based company goals are been reached satisfactorily. Some of the major importance of frontend development in relationship with UI and UX are:

  • Optimize navigation: Intuitive navigation will help gain customer trust by ensuring that the visitors find whatever they are seeking from your site. It majorly comprises of a well-planned site layout, clean, and structured impressive graphics.
  • Visitor retention: This will help increase traffic and conversion. Thus, optimized performance is one of the business benefits of front-end development.

Some other sub areas of its relevance are mobile frontend and web frontend:

  • Mobile Frontend: This can operate effectively without an active internet.
  • Web Frontend: This requires active internet for it work properly on your devices.

Generally, frontend development tools are focused on the user interface and user experiences. These has given birth to the following importance:

  • Creating modern day responsive websites or web app for mobility segment
  • Building bug free, secured and consistent products for high traffic web zone
  • Developing quickly reacting features or interactive app tools for online stores
  • Easy to learn, use and scale technologies, etc

In conclusion, the earlier you learn various frontend skills such as VueJS today – the better. Frontend courses are made easy with the best-qualified teaching procedures at German IT Academy.

Frontend in 2020

As for the prediction of where Frontend will head in 2020 it’s no easy task. Just as VueJS came out of nowhere and allowed more people with lower frontend skills to participate in the development. So can another framework, paradigm or tools do so in 2020.

Responsive stays

It is certainly though that Material Design & Bootstrap are going to continue growing like they already do. They will keep evolving and doing the little hard jobs of micro-designing small buttons and tables for us.

Changing Screen Sizes

If the rise of foldable phones continues, the frontend developers will need to adjust to this new environment of suddenly changing screen size and making sure that the app, page, game works transitions seamlessly between both screen sizes.

Performance & Data Focus

With the rise of data lakes and data on itself, Frontend Industry will be coming up with ways to make their Application lighter and more intelligent in showing, grouping and filtering the right information without overloading the hardware, browser, etc.

Artificial Intelligence in Frontend

With AI supported in-app & on website behaviour analysis of end consumers. We will have insight into deep psychology of our brains. What color triggers more excitement, what button animation triggers more dopamine, etc. The Frontend world will definitely become more fine tuned to our psychological “needs” in our to manipulate the end consumer to … consume.

Frontend in VR & AR

It’s totally new field for us. But one can imagine that Frontend will play a crucial role in AR and VR. This area brings a whole new set of challenges with itself. The user does not use a mouse or a keyboard. The user does stare a small screen. There could pop up a Framework like “ReactVR” (e.g. React 360) or something like that. Which would allow you do design 360 User Interfaces. Or something like “VueAR”, which would allow you to create transparent overlay User Interfaces to allow the user to use your app while they are interacting with their environment.

How to Run Moodle with Docker Compose

How to Run Moodle with Docker Compose

In this tutorial we are going to have a Moodle Instance up and running on a Virtual Machine – inside Docker Containers.

First of all, install and get Docker up and running. Then, download Moodle or make sure you have a Git-Repository ready at hand. We are going to use docker-compose for this task. Now let’s try and Run Moodle with Docker.

Moodle with Docker

We need a container that will have all the needed technology to run and serve the Moodle source code (your repository). This configuration will come from an Image, that we will use and configure through a docker-compose.yml file. Create a file docker-compose.yml and insert the version of docker-compose syntax that we are going to use:

version: "3.3"

These Technologies are needed:

  • Moodle Container
    • Operating System (Ubuntu)
    • Server (Apache2, Nginx)
    • PHP7.x (incl. php-curl, php-mysql, etc.)
  • Database Container
    • MariaDB 10+

Database Docker Image

We are going to use a simple and straightforward solution from bitnami. We simple create a service that will use this image, and set some parameters like username, db_name, etc.

services:
  mariadb:
    image: "bitnami/mariadb:10.1"
    networks:
      - moodle-net
    environment:
      - MARIADB_USER=bn_moodle
      - MARIADB_DATABASE=bitnami_moodle
      - ALLOW_EMPTY_PASSWORD=yes
    volumes:
      - type: bind
        source: /home/maria_data
        target: /bitnami
    ports:
      - "3306:3306"

We call our service ‘mariadb’, expose some ports (3306) and bind a volume to persist our data on our host machine. We also attach ‘mariadb’ to a network moodle-net. Also, make sure that docker can read/write the /home/maria_data folder on your host. We set rwx access for now (which is not recommended), please make sure to set the proper rights.

sudo chmod a+rwx /home/maria_data/

Server Docker Image

There are already built images for these technologies: webdevops/php-apache:7.3 & bitnami/mariadb.

Let’s pull and test the PHP & Apache image first.

#Download
docker pull webdevops/php-apache:7.3

# Run Image (Copy image ID. 'docker images')
docker run -d -p 80:80 efec3d223189

Now navigate to localhost or your public IP Address. You should see an empty Apache2 page.

Moodle and Docker

This page is the result of the file ‘index.php’ in container in folder /app. Worked fine. To use this image as a service in our config file, we need to create a new service in docker-compose.yml.

  moodle:
    image: "webdevops/php-apache:7.3"
    networks:
      - moodle-net
    environment:
      - MOODLE_DBHOST=mariadb
      - MOODLE_DBPORT=3306
      - MOODLE_DBUSER=bn_moodle
      - MOODLE_DBPASS=''
      - MOODLE_DBNAME=bitnami_moodle
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - type: bind
        source: /home/moodle_data
        target: /moodledata/moodledata
      - type: bind
        source: /home/gita-moodle
        target: /app
    depends_on:
      - mariadb

We specify the image that we tested previously. Specify the network to be same as the network of mariadb container. The Env Vars that we define, will be used by moodle in config.php. We open ports and specify the volumes. We make sure that moodle container only starts after mariadb container is up with the depends_on option. Make sure /home/moodle_data is writable.

sudo chmod a+rwx /home/moodle_data/

Before we continue, in these courses you can learn how to create backend and frontend application. Both of which you can easily deploy and serve with Docker. And now you know how to use docker-compose. Expand your skill-set with these courses.

Finish line

At last, we need to define our network and volumes:

networks:
  moodle-net:
    driver: bridge

volumes:
  mariadb_data:
    driver: local
  moodle_data:
    driver: local

Now let’s boot up these containers with and visit localhost or your public ip.

docker-compose up -d

You should see the installation process. Enter your Database data (see ENV VARS in MariaDB Service. After that a config.php file will be created. If not, copy the code and create a config.php file in root folder.

Moodle Installation process Docker

After finishing up the setup process of moodle, you’ll finally see your ready working moodle instance. Now you run Moodle with Docker Containers.

After setting up moodle. Your host volumes/folders will be filled with data that comes from containers. E.g. moodle population a predefined folder structure in moodle_data.

ls moodle_data/
cache  filedir  lang  localcache  lock  moodle  muc  sessions  temp  trashdir

Same, and more importantly, applies to mariadb container. Our Database is now persisted on our host machine.

/home/maria_data/mariadb/data# pwd
/home/maria_data/mariadb/data
/home/maria_data/mariadb/data# ls
aria_log.00000001  aria_log_control  bitnami_moodle  ibdata1  ib_logfile0  ib_logfile1  multi-master.info  mysql  mysql_upgrade_info  performance_schema  tc.log  test

Andrey Bulezyuk

German IT Academy Coach

Andrey Bulezyuk is the founder of German IT Academy and a course creator. He mainly covers topics from Web Development (NodeJS, VueJS, Django etc.) to Data Science (Pandas, Numpy) and Machine Learning (Tensorflow, Keras, etc.). He published a German book “Algorithmic Trading“, giving his readers the opportunity to learn how to code automatic trading systems for the stock market or the Forex. He has experience as a Backend and Frontend Developer. In his early years he worked on Web Projects as a Freelancer. Switched later to Financial Market System Developing. Currently employed as Machine Learning Engineer. He takes part in different projects and acts as a Co-Founder in different small start-ups. Andrey Bulezyuk was an employed Full-Stack Developer in Munich. Currently his duties do cover areas of Machine Learning and ETL.

Node.JS Tutorial: REST API & CRUD Operations

Node.JS Tutorial: REST API & CRUD Operations

The following Tutorial will guide you through creating a simple REST API and CRUD Operations. Our Stack is ExpressJS, Mongoose and MongoDB.

This API will perform CRUD Operations on Data stored in MongoDB. It’s best to start from scratch and try creating this app by yourself. After you tried creating the App with the help of this tutorial, you can go ahead and clone the working Github Repository here. https://github.com/AndreyBulezyuk/nodejsrestapi


Before you continue with this tutorial, please consider signing up for our Mailing List. You’ll get awesome free tutorials, podcasts, free and paid courses into your inbox.


What is REST API and CRUD Operations

REST stands for representation state transfer (wiki) and stands for a software architectural style with a set of constraints which lead to REST Service. Our service (our ExpressJS Server) is an Adapter to another backend service or database. Therefore we call it API.

CRUD is much simpler. The letters stand respectively for Create, Read, Update and Delete. Thus, CRUD stand for a set of operations that allows us to manipulate our states or data (through our REST API).

NPM – Creating the Project

Creating the project is the first step. Create a folder and inside that folder type

npm create

Fill out the following promts that’ll appear after npm create. Then we need to install following packages for our project:

npm install --save express@4.17.1
npm install -g nodemon@1.19.4
npm install --save mongoose@5.7.11

Once there, you should have a file ‘package.json’ in your folder that look like the code below. Note that i added “dev” to “scripts”, where we call nodemon. Nodemon allows us to restart the server automatically as soon as we update a file in our project.

{
  "name": "nodejsboostrap",
  "version": "1.0.0",
  "description": "Basic NodeJS Excercise for German IT Academy (git-academy.com)",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node index.js",
    "dev": "nodemon index.js"
  },
  "keywords": [
    "nodejs",
    "germanitacademy",
    "gitacademy",
    "expressjs",
    "nodemon"
  ],
  "author": "Andrey Bulezyuk @ German IT Academy",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1",
    "mongoose": "^5.7.11"
  }
}

In schema/ i added a new schema product.js which is pretty similar to the one you will find in the official docs. This is the Object Schema that we will be working with.

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var productSchema = new Schema({
  title:  String,
  author: String,
  body:   String,
  price: Number,
  comments: [{ body: String, date: Date }],
  date: { type: Date, default: Date.now }
});

var Product = mongoose.model('products', productSchema);
module.exports = Product

If you want to learn how to build VueJS Applications that can read from a REST API, take a look at our new VueJS Certification.

Express.JS – REST API Routes

Our Express.js backbone is pretty tiny, only 8 lines of code. We tell Express to use a bodyParser, so we can access the body as a JSON Object. We tell ExpressJS to use our product route and then we start the server.

const express = require('express')
const app = express()
const bodyParser = require('body-parser')
const product = require('./routes/product')

app.get('/', (req, res) => res.send('Hello from German IT Academy!'))
app.use(bodyParser.json())
app.use('/product', product)
app.listen(3000, () => console.log(`Example app listening on port 3000!`))

Just a quick test whether the server is up and ready!

C:\Users\andre>curl localhost:3000
Hello from German IT Academy!

Looks good. Now. Our product route is where all the magic actually happens. All our Documents in MongoDB will be created, read, updated and deleted from this place: routes/product.js.

Now let’s got through each Route (GET, POST, PATCH, DELETE) and see what mongoose method we used to make this work. Note, this is not the ultimate way to do it. Feel free to try out different Methods provided by Mongoose.

The first Route is a GET Route. Which means it only return the Entries in the Database by executing:

router.get('/', async function (req, res) {
    const products = await product.find().exec()
    res.send(products)
})
REST API Request with User Interface for REST API
A simple GET Request, to test whether our API returns the entries from MongoDB.

The POST Route insert new Entries into the MongoDB Database. It uses the data from the Request payload in JSON Format. It’s important to notice that the body payload has to have the right set of Attributes. Meaning that the Request initiator must know what Attributes a Product can/must have.

router.post('/', function (req, res) {
    product.create(req.body)
    res.send('POST Request accepted.')
})

The Patch Route is a bit more complicated. It is cause by the MongoDB Syntax of updating a Document. If we want to update only some Attributes/Keys of a MongoDB Document, we must use the key “$set: {}”. The req.body contains the updated values of attributes/keys for the specified Document. We specify what document to update via the URL Parameter id. Finally we’ll search through MongoDB for an Entry with the corresponding MongoDB “_id”!

router.patch('/:id', async function (req, res) {
    const result = await product.updateMany({
        "_id": String(req.params.id)
    }, { $set: req.body })
    res.send('PATCH Request accepted.')
})

Last and but not least, the Deletion of a Document. The Delete Route. We specify the “_id” of the DOcument in the URL and invoke the Mongoose DeleteMany() Method.

router.delete('/:id', async function (req, res) {
    const result = await product.deleteMany({
        "_id": String(req.params.id)
    })
    res.send('DELETE Request accepted.')
})

That is it, we are done, but, you probably want to see the whole code? Here you go:

var express = require('express')
var router = express.Router()
const mongoose = require('mongoose')
const product = require('../schema/product')
mongoose.connect('mongodb://localhost/nodejsrestapiboostrap', {
    useNewUrlParser: true,
    useUnifiedTopology: true 
});


router.get('/', async function (req, res) {
    const products = await product.find().exec()
    res.send(products)
})

router.post('/', function (req, res) {
    product.create(req.body)
    res.send('POST Request accepted.')
})

router.patch('/:id', async function (req, res) {
    const result = await product.updateMany({
        "_id": String(req.params.id)
    }, { $set: req.body })
    res.send('PATCH Request accepted.')
})

router.delete('/:id', async function (req, res) {
    const result = await product.deleteMany({
        "_id": String(req.params.id)
    })
    res.send('DELETE Request accepted.')
})

module.exports = router
VueJS Tutorial – #6 Template Syntax

VueJS Tutorial – #6 Template Syntax

Before we start with another VueJS Tutorial, let me promote our VueJS Course with a Certificate right at the beginning. You’ll see more interactive and deeper Content about VueJS. At the end you’ll also receive a VueJS Certificate from German IT Academy. That’s it.

Problem / Task

While coding a solution for the following tasks, make sure to make use of every single v-directive at least once: v-text, v-html, v-once and v-model. Also, do not forget to use conditional and iterative v-directives, if needed.

  • Create a new Vue Component CustomizeDonut.vue
  • Use following JSON Sample data as ‘donuts‘ data property
  • In CustomizeDonut, create 4-step input process, in which a user has to perform one data-selection in each step. Use v-model as much as you can. The steps should have individual h1 titles and individual Button Values.
    • Select Donut by name (see Sample Data)
    • Select Batter Type
    • Select Topping Type
    • Last step: Show the summary and a dummy button “Order Donut”

Hint

Here is a sample Object of a Donut. Few things stand out: We have a type and a name. We have a list of “batters” and “topping”, which contain object with further details.

	{
		"id": "0001",
		"type": "donut",
		"name": "Cake",
		"ppu": 0.55,
		"batters":
			{
				"batter":
					[
						{ "id": "1001", "type": "Regular" },
						{ "id": "1002", "type": "Chocolate" },
						{ "id": "1003", "type": "Blueberry" },
						{ "id": "1004", "type": "Devil's Food" }
					]
			},
		"topping":
			[
				{ "id": "5001", "type": "None" },
				{ "id": "5002", "type": "Glazed" },
				{ "id": "5005", "type": "Sugar" },
				{ "id": "5007", "type": "Powdered Sugar" },
				{ "id": "5006", "type": "Chocolate with Sprinkles" },
				{ "id": "5003", "type": "Chocolate" },
				{ "id": "5004", "type": "Maple" }
			]
	}
  • To have a multi-step process, you have to track the status of the current process. You can do it with an object. Or simpler yet, a variable that will store the step number that the user is currently performing.

Solution

Here is the solution we came up with for this VueJS Tutorial. Please that is no definite solution, except that the v-directive are used correctly. We smashed the solution into one Vue Component, that way we make it simpler to understand by not having the code in 3-4 different files.

<template>
  <div id="CustomizeDonut">
    <h1 v-text="stepConfig[step].title"></h1>
      <div v-if="step == 1">
            <select v-model="userInput.donutId">
                <option v-for="donut in donuts" :value="donut.id" :key="donut.id" v-text="donut.name"/>
            </select>
      </div>
      <div v-else-if="step == 2">
            <select v-model="userInput.batterId">
                <option v-for="batter in batters" :value="batter.id" :key="batter.id" v-text="batter.type"/>
            </select>
      </div>
      <div v-else-if="step == 3">
            <select v-model="userInput.toppingId">
                <option v-for="topping in toppings" :value="topping.id" :key="topping.id" v-text="topping.type"/>
            </select>
      </div>
      <div v-else-if="step == 4">
            Donut Id: {{userInput.donutId}}<br>
            Batter Id: {{userInput.batterId}}<br>
            Topping Id: {{userInput.toppingId}}<br>
      </div>
      <button @click="stepConfig[step].nextStep" v-text="stepConfig[step].button"/>
  </div>
</template>

<script>
    export default {
        name: "CustomizeDonut",
        data() {
            return {
                donuts: [{
                        "id": "0001",
                        "type": "donut",
                        "name": "Cake",
                        "ppu": 0.55,
                        "batters": {
                            "batter": [{
                                    "id": "1001",
                                    "type": "Regular"
                                },
                                {
                                    "id": "1002",
                                    "type": "Chocolate"
                                },
                                {
                                    "id": "1003",
                                    "type": "Blueberry"
                                },
                                {
                                    "id": "1004",
                                    "type": "Devil's Food"
                                }
                            ]
                        },
                        "topping": [{
                                "id": "5001",
                                "type": "None"
                            },
                            {
                                "id": "5002",
                                "type": "Glazed"
                            },
                            {
                                "id": "5005",
                                "type": "Sugar"
                            },
                            {
                                "id": "5007",
                                "type": "Powdered Sugar"
                            },
                            {
                                "id": "5006",
                                "type": "Chocolate with Sprinkles"
                            },
                            {
                                "id": "5003",
                                "type": "Chocolate"
                            },
                            {
                                "id": "5004",
                                "type": "Maple"
                            }
                        ]
                    },
                    {
                        "id": "0002",
                        "type": "donut",
                        "name": "Raised",
                        "ppu": 0.55,
                        "batters": {
                            "batter": [{
                                "id": "1001",
                                "type": "Regular"
                            }]
                        },
                        "topping": [{
                                "id": "5001",
                                "type": "None"
                            },
                            {
                                "id": "5002",
                                "type": "Glazed"
                            },
                            {
                                "id": "5005",
                                "type": "Sugar"
                            },
                            {
                                "id": "5003",
                                "type": "Chocolate"
                            },
                            {
                                "id": "5004",
                                "type": "Maple"
                            }
                        ]
                    },
                    {
                        "id": "0003",
                        "type": "donut",
                        "name": "Old Fashioned",
                        "ppu": 0.55,
                        "batters": {
                            "batter": [{
                                    "id": "1001",
                                    "type": "Regular"
                                },
                                {
                                    "id": "1002",
                                    "type": "Chocolate"
                                }
                            ]
                        },
                        "topping": [{
                                "id": "5001",
                                "type": "None"
                            },
                            {
                                "id": "5002",
                                "type": "Glazed"
                            },
                            {
                                "id": "5003",
                                "type": "Chocolate"
                            },
                            {
                                "id": "5004",
                                "type": "Maple"
                            }
                        ]
                    }
                ],
                step: 1, // We start with step 1
                stepConfig: {
                    1: {
                        title: "Donut Type",
                        button: `Go to Step 2`,
                        nextStep: () => {this.step = 2;}
                    },
                    2: {
                        title: "Batter Type",
                        button: `Go to Step 3`,
                        nextStep: () => {this.step = 3;}
                    },
                    3: {
                        title: "Topping Type",
                        button: `Final Step`,
                        nextStep: () => {this.step = 4;}
                    },
                    4: {
                        title: "Your Donut",
                        button: `Send order and Start over`,
                        nextStep: () => {this.step = 1;}
                    },
                },
                userInput: {
                    donutId: 0,
                    batterId: 0,
                    toppingId: 0
                }
            }
        },
        computed: {
            batters: {
                get() {
                    const currentDonut = this.donuts.filter(item => item.id == this.userInput.donutId)
                    return currentDonut[0].batters.batter
                }
            },
            toppings: {
                get() {
                    const currentDonut = this.donuts.filter(item => item.id == this.userInput.donutId)
                    return currentDonut[0].topping
                }
            }
        }
    }
</script>

<style>
button, option, select {
    margin: 20px 20px 20px 20px;
    font-size: 30px;
    color: rgb(255, 255, 255);
    background: rgba(255, 106, 0, 0.972)
}
</style>

Here is quite a lot happening, let’s go trough it.

First we have created a very simple step process by having a step data property and showing conditional HTML content based on that property; we achieve this with v-if and v-else-if v-directives.

Our data property stepConfig tells our App what title, what button text and what the button-action should be. Notice that we use a function for stepConfig.nextStep; this is because we use the v-directive v-on on our button. This directive needs a function as a parameter. @click=”stepConfig[step].nextStep”

Our computed properties help us extract or filter the correct batters and topping for the donut selected by the user.

In order to store user Input we created an object userInput and we mapped the keys “userInput.donutId”, “userInput.batterId” and “userInput.toppingId” with v-model to the select.options HTML Tags. This way our App has always the most recent user input saved in this Object.

If you want to learn more about VueJS and become a VueJS Certified Developer, please take a look at our VueJS Course + Certificate.

Here is a visual version of our solution. Please note, we know VueJS, but we suck at Design.

VueJS Tutorial- #5 Component Relationships

VueJS Tutorial- #5 Component Relationships

Welcome to another VueJS Tutorial. Let’s explore a very important topic in VueJS: the relationship between your Vue-Components. It’s crucial because everything is importing everything from everywhere anytime…or something like this.

For those who are new to VueJS Tutorial / VueJS Practice: we create a fictional problem / task for you to solve. To go through it and try and code a solution that would solve the issue. Then you compare it with the solution provided by German IT Academy.

Problem / Task

We need

  • create DataSourceList.vue that reads from state ‘datasources’ in vuex store.
  • For every Entry in the ‘datasources’ list, embed a a DataSourceItem.vue in the DataSourceList.vue.
  • DataSourceItem Component receives the props ‘id’ from the Parent. With that id the Child fetches all the data from ‘datasources’ in vuex store and displays them.
  • DataSourceItem Component receives a slot from the Parent and displays the content in a random place.

Hint

  • When importing a Vue-Component, do not forget to also import it inside the Parent Instance
  • As reminder, props are those data values that you pass to a child as a HTML Tag Attribute (:propName=data) and slot is the data between the HTML Opening and Closing tag.
  • To create Vuex Getter that receives a parameter from the outside, read: https://vuex.vuejs.org/guide/getters.html

You can learn more about VueJS with our VueJS Course and get VueJS certified.

Solution

Source code:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    datasources: [
      {
        id:0,
        name:'Google Cloud Storage',
        interface: 'REST API',
        activated: true
      },
      {
        id:1,
        name:'AWS S3 Bucket',
        interface: 'REST API',
        activated: true
      },
      {
        id:2,
        name:'On-Deman Server Storage',
        interface: 'SSH',
        activated: false
      }
    ]
  },
  getters: {
    getAllDataSources(state) {
      return state.datasources
    },
    getDataSourceById: (state) => (id) => {
      for (let i = 0; i < state.datasources.length; i++) {
        if (state.datasources[i].id == id) {
          return state.datasources[i]
        }
      }
    }
  },
  mutations: {
  },
  actions: {
  }
})

We have the list as a state variable. We have to getters: one for every DataSource and one getter that will return only the Entry with the specified id.

<template>
  <div class="DataSourceItem">
    <h2 :style="activated()"> 
      {{this.datasource.name}}
    </h2>
    <h3> {{datasource.interface}}</h3>
  </div>
</template>

<script>
export default {
  name: 'DataSourceItem',
  props: {
    id: Number
  },
  computed: {
    datasource: {
      get(){
        return this.$store.getters.getDataSourceById(this.id)
      }
    }
  },
  methods: {
    activated() {
      if (this.datasource.activated) {
        return 'background-color:green;'
      }
      return 'background-color:red;'
    }
  }
}
</script>

<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

The DataSourceItem.vue receives the id as a props. With that id the Component will retrieve the DataSource from Vuex Store. It’ll use the Vuex getter that we’ll define below.

<template>
  <div class="home">
    <img 
      alt="German IT Academy"
      width="200"
      src="https://i0.wp.com/code.git-academy.com/wp-content/uploads/2019/10/400dpiLogo.jpg?zoom=1.100000023841858&fit=2077%2C1175&ssl=1">
    <div v-for="datasource in datasources" :key="datasource.id">  
      <DataSourceItem :id="datasource.id"/>
    </div>
  </div>
</template>

<script>
// @ is an alias to /src
import DataSourceItem from '@/components/DataSourceItem.vue'

export default {
  name: 'DataSourceList',
  components: {
    DataSourceItem
  },
  computed: {
    datasources: {
      get(){
        return this.$store.getters['getAllDataSources']
      }
    },
  }
}
</script>

German IT Academy hopes you learned something new with this VueJS Tutorial. You can learn more about VueJS with our VueJS Course and get VueJS certified.

The visual version of the solution looks like this.

VueJS Course and VueJS Certificate