Dyploma is a system for managing containerized applications and services on top of Kubernetes in Outbrain. Dyploma includes the concepts of:

  • artifacts
  • builds
  • deployments
  • services

Dyploma includes Java Spring backend and a Python command-line tool (CLI). The command-line tool operates through API calls to the backend.

The Dyploma Web Application

The web application will operate by fetching data from the backend and sending operations for execution at the backend. This will be done through the same REST API used by the CLI.

Why Typeahead?

  • artifacts
  • builds
  • deployments
  • services
  • environments
  • kube clusters

In each case, typeahead is relative to a different field in the data.

Why Another Typeahead Component?

We decided to base our component on Let’s build Type Ahead Component with VueJS 2 and Fetch API. However, its usage of transition groups not good for us. And it did not provide for customisation of the typeahead field.

Our Typeahead

One can customise the field on which it operates. It interacts with your backend through promises.

It gets two props:

  • startAt - how many characters to wait before trying to fetch the list of corresponding options from the server
  • field - a structure describing the typeahead field

The Field

{
key: 'serviceId',
autocomplete: 'name',
placeholder: 'Select a service',
}

The Result

this.$emit('selected', { field: this.field.key, value: item.id });

Where:

  • field: the key of the field
  • value: the id of the selected option

The Backend

You will need to write it for your case.

We assume the data contains an id field identifying the selected item.

The Template

The Top Level

< div class="typeahead">
< /div>

The Input Box

< input 
v-model="query"
@focus="reset"
type="text"
class="search-input"
v-bind:placeholder="field.placeholder"
>

List of Possible Options

< ul class="results" v-if="!selected">
< li
v-for="item in items"
:key="item.id"
v-on:click="selectedItem(item)"
>
< span>
< strong>{{ item.value }}< /strong>
< /span>
< /li>
< /ul>

The Code

import _ from 'lodash';

import backand from `@/backend`;

export default {
name: 'typeahead',
props: ['startAt', 'field'],

data() {
return {
items: [],
query: '',
selected: false,
};
},

computed: {
isEmpty() {
if (!this.query) {
return false;
}
return this.items.length < 1;
},
},

methods: {
fetchItems() {
const q = this.query.trim();
backand.getAutocomplete(q, this.field.key)
.then((results) => {
this.items = this.extractItems(results, this.field);
});
},
extractItems(results, field) {
return _.concat([{ id: null, value: 'none selected' }], _.map(results, r => ({ id: r.id, value: r[this.field.autocomplete] })));
},
reset() {
this.items = [];
this.selected = false;
},
selectedItem(item) {
this.selected = true;
if (item.id) {
this.query = item.value;
this.$emit('selected', { field: this.field.key, value: item.id });
} else {
this.query = '';
}
},
},

watch: {
query(to, from) {
if (this.query.trim().length >= this.startAt) {
this.fetchItems();
}
},
},
};

The Styling

$height: 18.95vh;

.typeahead {

flex: 2;
height: $ * 0.2;

.search-input {
position: relative;
width: 100%;
height: $height * 0.2;


font-family: AvenirNext;
font-size: 14px;
font-weight: bold;
text-align: left;
color: #a7aaac;

margin: 0;
padding: 0;

font-size: 1em;
outline: 0;
position: relative;
color: #2e3d42;

}

.search-input::placeholder {
font-family: AvenirNext;
font-size: 14px;
font-weight: bold;
text-align: left;
color: #2e3d42;
padding-left: 5%;
}

.search-input:hover {
border: 1px solid #0097ce;
}

.search-input:focus {
border: 1px solid #0097ce;
}

.search-input:active {
border: 1px solid #0097ce;
}

.results {
margin: 0;
padding: 0;
text-align: left;
position: relative;
opacity: 1;
z-index: 1000;


li {

font-family: AvenirNext;
font-size: 14px;
font-weight: bold;
text-align: left;
color: #2e3d42;

background-color: #fdfefe;

margin: 0;
padding: 1em;
list-style: none;
width: 100%;
}

}

}

The Code

Written by

Open source, Mobile, Web, Cloud, Server - Independent Information Technology and Services Professional http://yoramkornatzky.com kornatzky@gmail.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store