I have an application, in which the frontend is implemented in Vue and the backend uses FastAPI framework. The communication is achieved through websockets.
Currently, the frontend allows the user to enter a term, which is sent to the backend to generate the autocomplete and also perform a search on a URL that returns a JSON object. In which, I save this JSON object in the frontend folder. After that, the backend returns the autocomplete data for the term in question to the frontend. The frontend displays the aucomplete along with the json data.
However, when I studied a little more, I noticed that there is a way to send the JSON returned by the request URL to Vue (frontend), without having to save it locally, avoiding giving an error of not allowing to execute this process more than once.
My current code is as follows. For FastAPI (backend):
@app.websocket("/")
async def predict_question(websocket: WebSocket):
await websocket.accept()
while True:
input_text = await websocket.receive_text()
autocomplete_text = text_gen.generate_text(input_text)
autocomplete_text = re.sub(r"[\([{})\]]", "", autocomplete_text)
autocomplete_text = autocomplete_text.split()
autocomplete_text = autocomplete_text[0:2]
resp = req.get('www.description_url_search_='+input_text+'')
datajson = resp.json()
with open('/home/user/backup/AutoComplete/frontend/src/data.json', 'w', encoding='utf-8') as f:
json.dump(datajson, f, ensure_ascii=False, indent=4)
await websocket.send_text(' '.join(autocomplete_text))
File App.vue (frontend):
<template>
<div class="main-container">
<h1 style="color:#0072c6;">Title</h1>
<p style="text-align:center; color:#0072c6;">
Version 0.1
<br>
</p>
<Autocomplete />
<br>
</div>
<div style="color:#0072c6;">
<JsonArq />
</div>
<div style="text-align:center;">
<img src="./components/logo-1536.png" width=250 height=200 alt="Logo" >
</div>
</template>
<script>
import Autocomplete from './components/Autocomplete.vue'
import JsonArq from './components/EstepeJSON.vue'
export default {
name: 'App',
components: {
Autocomplete,
JsonArq: JsonArq
}
}
</script>
<style>
.main-container {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
font-family: 'Fredoka', sans-serif;
}
h1 {
font-size: 3rem;
}
@import url('https://fonts.googleapis.com/css2?family=Fredoka&display=swap');
</style>
Autocomplete.vue file in the components directory:
<template>
<div class="pad-container">
<div tabindex="1" @focus="setCaret" class="autocomplete-container">
<span @input="sendText" @keypress="preventInput" ref="editbar" class="editable" contenteditable="true"></span>
<span class="placeholder" contenteditable="false">{{autoComplete}}</span>
</div>
</div>
</template>
<script>
export default {
name: 'Autocomplete',
data: function() {
return {
autoComplete: "",
maxChars: 75,
connection: null
}
},
mounted() {
const url = "ws://localhost:8000/"
this.connection = new WebSocket(url);
this.connection.onopen = () => console.log("connection established");
this.connection.onmessage = this.receiveText;
},
methods: {
setCaret() {
const range= document.createRange()
const sel = window.getSelection();
const parentNode = this.$refs.editbar;
if (parentNode.firstChild == undefined) {
const emptyNode = document.createTextNode("");
parentNode.appendChild(emptyNode);
}
range.setStartAfter(this.$refs.editbar.firstChild);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
},
preventInput(event) {
let prevent = false;
// handles capital letters, numbers, and punctuations input
if (event.key == event.key.toUpperCase()) {
prevent = true;
}
// exempt spacebar input
if (event.code == "Space") {
prevent = false;
}
// handle input overflow
const nChars = this.$refs.editbar.textContent.length;
if (nChars >= this.maxChars) {
prevent = true;
}
if (prevent == true) {
event.preventDefault();
}
},
sendText() {
const inputText = this.$refs.editbar.textContent;
this.connection.send(inputText);
},
receiveText(event) {
this.autoComplete = event.data;
}
}
}
</script>
EstepeJSON.ue file in the components directory:
<template>
<div width="80%" v-for="regList in myJson" :key="regList" class="container">
<table>
<thead>
<tr>
<th>Documento</th>
</tr>
</thead>
<tbody>
<tr v-for="countryList in regList[2]" :key="countryList">
<td style="visibility: visible">{{ countryList}}</td>
</tr>
</tbody>
</table>
</div>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css"
/>
</template>
<script>
import json from "@/data.json";
export default {
name: "EstepeJson",
data() {
return {
myJson: json,
};
},
};
</script>
Example of the JSON returned by the URL:
[
{
"Title": "SOFT-STARTER",
"Cod": "Produto: 15775931",
"Description": "A soft-starter SSW7000 permite o controle de partida/parada e proteção de motores.",
"Technical_characteristics": ["Corrente nominal", "600 A", "Tensão nominal", "4,16 kV", "Tensão auxiliar", "200-240 V", "Grau de proteção", "IP41", "Certificação", "CE"]
},
{
"Title": "SOFT-STARTER SSW",
"Cod": "Produto: 14223395",
"Description": "A soft-starter SSW7000 permite o controle de partida/parada e proteção de motores de indução trifásicos de média tensão.",
"Technical_characteristics": ["Corrente nominal", "125 A", "Tensão nominal", "6,9 kV", "Tensão auxiliar", "200-240 V", "Grau de proteção", "IP54/NEMA12", "Certificação", "CE"]
}
]