Vue3 data is null - axios

I've created a small sample with vuejs3 to display some data.
I do have connection to the server. I had a CORS issue but have configured a proxy to access data from the client.
main.js
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
App.vue
<template>
<div class="container mt-5">
<div class="row">
<div class="col-12">
<contract-data/>
</div>
</div>
</div>
</template>
<script>
import ContractData from "./components/ContractData.vue";
export default {
name: "App",
components: {
ContractData,
}
}
ContractData.vue
<template>
<table class="table">
<tr><td>Contract-Id</td><td>{{ contractData.id }}</td></tr>
</table>
</template>
<script>
import axios from 'axios';
export default {
name: "contract-data",
data() {
return {
contractData: null
};
},
async created() {
const response = await axios.get("http://localhost:8080/contract/123456");
console.log(response.data);
this.contractData = response.data;
}
};
</script>
The thing is: I see the json data returned in the console.log statement in the async block. However it seems that the assignement to contractData is not working.

Related

Validate multiple selects with a vue Form

I am new to Vue and I am trying to validate a form made by multiple select rendered by a vfor. The date is coming from a Json, simulated mock-server-json.
I can use Vue Vanilla or vee-validate. I saw I could use useFieldArray with vee-validate but I could not make it work.
<template>
<ux-loader v-if="dataArray.length == 0" loading></ux-loader>
<transition name="onEnter">
<div v-if="dataArray.length != 0">
<form #submit.prevent="handleSubmit">
<div class="form">
<div v-for="(data, index) in dataArray" :key="index" class="select">
{{ index }}
<ux-input-a11y-select v-model="form.selected[index]">
<option data-placeholder value="">-- Choisir une valeur --</option>
<option v-for="option in data.option" :key="option" :value="option">{{ option }}</option>
</ux-input-a11y-select>
</div>
</div>
<button class="submit">Valider</button>
</form>
<Modal v-show="isModalVisible" #close="closeModal" />
</div>
</transition>
<div v-if="error != null">{{ error }}</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
import Modal from '../components/Modal.vue'
import { UxBtn, UxInputA11ySelect, UxLoader } from '#libui/ux-default-lib'
import getForm from '../composables/getForm.js'
import postForm from '../composables/postForm.js'
UxInputA11ySelect.define()
UxBtn.define()
UxLoader.define()
export default defineComponent({
name: 'FormUser',
components: {
Modal,
},
setup() {
const dataArray = ref([])
const { error, load } = getForm()
const { sendData } = postForm()
load().then((result: any) => {
dataArray.value = result
})
return { sendData, error, dataArray }
},
data() {
return {
isModalVisible: false,
form: {
selected: [],
},
}
},
methods: {
handleSubmit() {
this.isModalVisible = true
},
async closeModal() {
this.isModalVisible = false
console.log(this.form.selected)
console.log(Object.values(this.form.selected))
this.sendData(this.form.selected)
this.$router.push('Display')
},
},
})
</script>
This is my current code. It is working as I can get an object containing the results of the selects but I am wondering if there is a better way of doing it, like in Angular where you get an object with all results without doing anything particular.
Any help appreciated.

Meteor: Can't display my collections

I have a collection named by "btso". I just tried to display this collection from this database but it doesn't display. I don't know if i have any errors in my code.
Here is main.html
<head>
<title>Sanji</title>
</head>
<body>
<div class="container">
<h4>Sanji's first meteor app</h4>
<ul class="collection">
{{> sanji}}
</ul>
</div>
</body>
<template name="sanji">
{{#each btso}}
<li class="collection-item">{{text}}</li>a
{{/each}}
</template>
Here is my main lib/collections.js
import { Mongo } from 'meteor/mongo';
export const Btso = new Mongo.Collection('btso');
And here is my main.js
import { Template } from 'meteor/templating';
import { Btso } from '../lib/collections.js';
import './main.html';
Template.sanji.helpers({
btso: function(){
return Btso.find({});
}
});

Send JSON data to server from react without rerender the page

I'm a bit new to ReactJS,
I've created a simple form and table, each time I hit the submit the state of the table change with the new data.
I'm using tornado as a backend server and mongodb as my DB.
I'm looking for a way to send the same JSON to the server on a second pipe (without rerendering the page again.)
How can I do it?
---- edit - react component -----
import Re
act from 'react';
export default class Reblaze_Dashboard extends React.Component {
constructor(props) {
super(props);
this.onNewUser = this.onNewUser.bind(this);
this.state = {
data: window.obj,
};
}
onNewUser(e) {
e.preventDefault();
const formData = {};
for (const field in this.refs) {
formData[field] = this.refs[field].value;
}
this.state.data.push(formData);
this.setState({
data: this.state.data,
});
}
render() {
return(
<div>
<h2>Dashboard page</h2>
<form onSubmit={this.onNewUser}>
<div className="form-group">
<label htmlFor="first-name-input">First name:</label>
<input type="text" className="form-control" ref="firstname" id="first-name-input" />
</div>
<div className="form-group">
<label htmlFor="last-name-input">Last name:</label>
<input type="text" className="form-control" ref="lastname" id="last-name-input" />
</div>
<input type="submit" value="Submit" className="btn btn-primary pull-right" />
</form>
<br /><br />
<div className="table-responsive">
<table className="table table-striped table-hover">
<thead>
<tr>
<td><h4>First name</h4></td>
<td><h4>Last name</h4></td>
</tr>
</thead>
<tbody>
{this.state.data.map((line, key) =>
<tr key={key}>
<td>{line.firstname}</td>
<td>{line.lastname}</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
)
}
}
You're submitting form data and immediately updating table without checking if your data reaches the server. This way it is possible to update user view while failing to update the database.
I strongly recommend to use some promise-based HTTP-client like Axios (https://github.com/mzabriskie/axios). Send some request, then wait for the promise resolve, and only after that update your component state.
You need something like this:
import React from 'react';
import axios from 'axios';
/*...*/
onNewUser(e) {
e.preventDefault();
const formData = {};
for (const field in this.refs) {
formData[field] = this.refs[field].value;
}
axios.post('yourApiUrl', formData)
// if request is sent and status is ok, update form and send second request
.then((res) => {
this.state.data.push(formData);
this.setState({
data: this.state.data,
});
return axios.post('yourApiUrl', formData);
})
// if second request is ok, receive a notification
.then((res) => {
console.log('second request is ok');
})
// if there is an error, receive a notification
.catch((err) => {
console.log(err);
})
}
/*...*/

Upload image in Angular 4 and save to Mongoose DB

There are other questions out there about uploading images with Angular 4, but NO comprehensive answers. I have played around with ng2-file-upload and angular2-image-upload, but can't get them to save in my Mongo/Mongoose DB. Here is what I have to far...
Component HTML:
<form (submit)="newProduct(formData)" #formData="ngForm">
<div class="form-group">
<label for="name">Product Name:</label><input type='text' name='name' class="form-control" id="name" ngModel>
</div>
<div class="form-group">
<label for="image">Image:</label><input type="file" name='image' class="form-control" id="image" ngModel>
</div>
<div class="form-group">
<label for="description">Description:</label><input type='text' name='description' class="form-control" id="description" ngModel>
</div>
<div class="form-group">
<label for="quantity">Quantity:</label><input type='number' name='quantity' class="form-control" id="quantity" ngModel>
</div>
<button type="submit" class="btn btn-default">Add</button>
</form>
Component.ts
import { Component, OnInit } from '#angular/core';
import { AddService } from './add.service';
...
export class AddComponent implements OnInit {
constructor(private _addService:AddService) { }
ngOnInit() {
}
newProduct(formData){
this._addService.addProduct(formData.value)
.then(()=>{
formData.reset()
})
.catch(err=>console.log(err))
}
}
Compoenent service
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import 'rxjs';
#Injectable()
export class AddService {
constructor(private _http:Http) { }
addProduct(newprod){
return this._http.post('/api/newprod', newprod).map((prod:Response)=>prod.json()).toPromise();
}
}
Controller
addProduct:(req,res)=>{
let newProd = new Product(req.body);
newProd.save((err,savedProd)=>{
if(err){
console.log("Error saving product");
} else {
res.json(savedProd);
}
})
},
Schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ProductSchema = new Schema({
name: {type:String,required:true},
image: {data:Buffer, contentType:String},
description: {type:String,required:true},
quantity: {type:Number,required:true},
}, {timestamps:true})
var Product = mongoose.model('Product', ProductSchema);
All of the other inputs make it back to the DB fine. What do I need to do to get the images saving properly?
I am afraid you can't directly upload image like that. First you can access image data from file tag and assign into formdata.
you can try like this.In your component
newProduct(formData){
let inputEl: HTMLInputElement = this.el.nativeElement.querySelector('#image');
let fileCount: number = inputEl.files.length;
let formData = new FormData();
if (fileCount > 0) {
formData.append('image', inputEl.files.item(0));
}
this._addService.addProduct(formData.value)
.then(()=>{
formData.reset()
})
.catch(err=>console.log(err))
}
}
this is not exact working solution but you can start like this.

Show loading image on each api call till response comes in axios library globally

Sometimes, when we call an api,it takes long time to respond so we prefer to show loading image till response come.
there is start and end event in ajax request to show loading image , I want same kind of stuff in axios.
I want to make it globally for each request in axios library for react.
please suggest me something for this.
import React, {Component} from 'react';
import axios from 'axios';
import loading from '../loading.gif' // relative path to image
class Home extends Component {
constructor() {
super()
this.state = {
time: null,
loading: true,
retJobs: []
}
this.getJobs();
}
getJobs() {
axios.get('http://example.com/getData.php')
.then(response => {
this.setState({retJobs: response.data});
console.log(response);
console.log(this.state.retJobs.results.length);
console.log(this.state.retJobs.results);
this.setState({
time: response.data.time,
loading: false
});
})
.catch(function (error) {
console.log(error);
});
}
render() {
let content;
if (this.state.loading) {
content = <img src={loading} alt="loading"/>// or another graceful content
} else {
content = <p className="jobCount">Found {this.state.retJobs.results.length} Jobs</p>;
}
return (
<div>
<h4>Home</h4>
<div className="App-intro">
<div className="container">
<div className="row mainContent">
<div className=" row mainContent">
{content}
{this.state.retJobs.results && this.state.retJobs.results.map(function (item, idx) {
return <div key={idx} className="col-lg-12">
<div className="jobs">
<div className="row jobHeader">
<div className="col-lg-6">
<h1>{item.jobTitle}</h1>
</div>
<div className="col-lg-6">
<h3>{item.locationName}</h3>
</div>
</div>
<div className="row">
<div className="col-lg-2">
<h2>{item.employerName}</h2>
</div>
<div className="col-lg-10">
<p>{item.jobDescription}</p>
</div>
</div>
</div>
</div>
})}
</div>
</div>
</div>
</div>
</div>
);
}
}
export default Home;