Odoo Popup button not working (JS, xml, Controller and manifest to troubleshoot) - odoo

I have the following code:
odoo.define('ebs_portal_attendance.mn_tasks', function (require) {
"use strict";
$(document).ready(function () {
// Show create timesheet popup
$('#create_timesheet_button').on('click', function () {
var $modal = $('#create_timesheet_popup');
var task_id = $(this).data('task-id');
$modal.modal('show');
});
// Create timesheet
$('#create_timesheet_popup #create_timesheet_button').on('click', function () {
var $modal = $('#create_timesheet_popup');
var task_id = $modal.find('#task_id').val();
var name = $modal.find('#name').val();
var unit_amount = $modal.find('#unit_amount').val();
var date = $modal.find('#date').val();
ajax.jsonRpc("/my/tasks/create_timesheet", 'call', {
'values': {
'name': name,
'task_id': task_id,
'unit_amount': unit_amount,
'date': date,
}
}).then(function (result) {
if (result.success) {
$modal.modal('hide');
alert("Timesheet created successfully!");
} else {
alert("An error occurred while creating the timesheet.");
}
});
});
});
});
<template id="mn_tasks_list" inherit_id="project.portal_tasks_list">
<xpath expr="//t//t//t//tbody//t//tr//td[last()]" position="after">
<td>
<div class="o_download_pdf btn-toolbar flex-sm-nowrap">
<div>
<a role="button" class="btn btn-secondary flex-grow-1 mb-1 create_timesheet_button"
data-toggle="modal"
id='create_timesheet_button' data-target="#create_timesheet_popup" href="#">
<t>Create Timesheet</t>
</a>
</div>
</div>
</td>
</xpath>
</template>
</data>
<template id="create_timesheet_popup" name="Create Timesheet Popup">
<div id="create_timesheet_popup" class="modal fade">
<div class="modal-dialog modal-content"
style="border:solid 2px white; min-height:200px;max-width:800px;margin-top:10px">
<div class="modal-body" id="pop_html">
<a href="#" class="o_popup_btn_close o_not_editable o_default_snippet_text pull-right"
data-dismiss="modal" aria-hidden="true">X</a>
<div class="row">
<div class="col-md-12">
<form class="o_form_sheet">
<div class="o_form_sheet_name">
<h4>Create Timesheet</h4>
</div>
<div class="form-group">
<label for="name">Name:</label>
<input type="text" class="form-control" id="name" name="name" required="required"/>
</div>
<div class="form-group">
<label for="task_id">Task:</label>
<select class="form-control" id="task_id" name="task_id" required="required">
<t t-foreach="tasks" t-as="task">
<option value="{{ task.id }}">{{ task.name }}</option>
</t>
</select>
</div>
<div class="form-group">
<label for="unit_amount">Hours:</label>
<input type="number" class="form-control" id="unit_amount" name="unit_amount"
required="required"/>
</div>
<div class="form-group">
<label for="date">Date:</label>
<input type="date" class="form-control" id="date" name="date" required="required"/>
</div>
<div class="form-group">
<button type="button" class="btn btn-primary" id="create_timesheet_button" data-task-id="{{ task.id }}">Create Timesheet</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</template>
#http.route('/my/tasks/create_timesheet', type='json', auth='user')
def create_timesheet(self, values):
task_id = values.get('task_id')
name = values.get('name')
unit_amount = values.get('unit_amount')
date = values.get('date')
try:
# Create new timesheet record
new_timesheet = http.request.env['account.analytic.line'].sudo().create({
'name': name,
'task_id': task_id,
'unit_amount': unit_amount,
'date': date,
})
# Return success message
return {'success': True, 'message': 'Timesheet created successfully'}
except Exception as e:
# Return error message
return {'success': False, 'message': 'An error occurred while creating the timesheet: %s' % e}
with the manifest is as follows:
` # always loaded
'data': [
'security/security.xml',
'security/ir.model.access.csv',
'views/views.xml',
'views/templates.xml',
'views/inherited_templates.xml',
],
'assets': {
'web.assets_backend': [
'model_folder/static/src/js/portal_timesheets.js',
],
},`
My Problem is that button on the portal in the list of tasks where the button is located it's there but now it's not doing anything i tried checking the js via adding console.log("test") to see if anything would appear under the web browser's console but there's nothing... what i am doing wring here please do help me.
Thank you!!
I'm looking to have it work where when the user clicks on create timesheet, a popup would appear and it'll take the task's ID and task.analytical_account_id.id and other inputs to which it'll create at the end a record for that model and appears under his timesheets.

Related

The below given code is not working for me. And giving an error "vueuploadComponent.html:396 Uncaught ReferenceError: FileUpload is not defined"

Here is the code in vue.js for multi Image uploading. Actually this code is not working for me I am facing an error "vueuploadComponent.html:396 Uncaught ReferenceError: FileUpload is not defined". So here I thing i doing some thing wrong with import a module. So please let me know where I am going wrong.
<template>
<div id = "vueUpload" class="example-full">
<button type="button" class="btn btn-danger float-right btn-is-option" #click.prevent="isOption = !isOption">
<i class="fa fa-cog" aria-hidden="true"></i>
Options
</button>
<h1 id="example-title" class="example-title">Full Example</h1>
<div v-show="$refs.upload && $refs.upload.dropActive" class="drop-active">
<h3>Drop files to upload</h3>
</div>
<div class="upload" v-show="!isOption">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>#</th>
<th>Thumb</th>
<th>Name</th>
<th>Width</th>
<th>Height</th>
<th>Size</th>
<th>Speed</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr v-if="!files.length">
<td colspan="9">
<div class="text-center p-5">
<h4>Drop files anywhere to upload<br/>or</h4>
<label :for="name" class="btn btn-lg btn-primary">Select Files</label>
</div>
</td>
</tr>
<tr v-for="(file, index) in files" :key="file.id">
<td>{{index}}</td>
<td>
<img class="td-image-thumb" v-if="file.thumb" :src="file.thumb" />
<span v-else>No Image</span>
</td>
<td>
<div class="filename">
{{file.name}}
</div>
<div class="progress" v-if="file.active || file.progress !== '0.00'">
<div :class="{'progress-bar': true, 'progress-bar-striped': true, 'bg-danger': file.error, 'progress-bar-animated': file.active}" role="progressbar" :style="{width: file.progress + '%'}">{{file.progress}}%</div>
</div>
</td>
<td>{{file.width || 0}}</td>
<td>{{file.height || 0}}</td>
<td>{{$formatSize(file.size)}}</td>
<td>{{$formatSize(file.speed)}}</td>
<td v-if="file.error">{{file.error}}</td>
<td v-else-if="file.success">success</td>
<td v-else-if="file.active">active</td>
<td v-else></td>
<td>
<div class="btn-group">
<button class="btn btn-secondary btn-sm dropdown-toggle" type="button">
Action
</button>
<div class="dropdown-menu">
<a :class="{'dropdown-item': true, disabled: file.active || file.success || file.error === 'compressing' || file.error === 'image parsing'}" href="#" #click.prevent="file.active || file.success || file.error === 'compressing' ? false : onEditFileShow(file)">Edit</a>
<a :class="{'dropdown-item': true, disabled: !file.active}" href="#" #click.prevent="file.active ? $refs.upload.update(file, {error: 'cancel'}) : false">Cancel</a>
<a class="dropdown-item" href="#" v-if="file.active" #click.prevent="$refs.upload.update(file, {active: false})">Abort</a>
<a class="dropdown-item" href="#" v-else-if="file.error && file.error !== 'compressing' && file.error !== 'image parsing' && $refs.upload.features.html5" #click.prevent="$refs.upload.update(file, {active: true, error: '', progress: '0.00'})">Retry upload</a>
<a :class="{'dropdown-item': true, disabled: file.success || file.error === 'compressing' || file.error === 'image parsing'}" href="#" v-else #click.prevent="file.success || file.error === 'compressing' || file.error === 'image parsing' ? false : $refs.upload.update(file, {active: true})">Upload</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" #click.prevent="$refs.upload.remove(file)">Remove</a>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="example-foorer">
<div class="footer-status float-right">
Drop: {{$refs.upload ? $refs.upload.drop : false}},
Active: {{$refs.upload ? $refs.upload.active : false}},
Uploaded: {{$refs.upload ? $refs.upload.uploaded : true}},
Drop active: {{$refs.upload ? $refs.upload.dropActive : false}}
</div>
<div class="btn-group">
<file-upload
class="btn btn-primary dropdown-toggle"
:post-action="postAction"
:put-action="putAction"
:extensions="extensions"
:accept="accept"
:multiple="multiple"
:directory="directory"
:create-directory="createDirectory"
:size="size || 0"
:thread="thread < 1 ? 1 : (thread > 5 ? 5 : thread)"
:headers="headers"
:data="data"
:drop="drop"
:drop-directory="dropDirectory"
:add-index="addIndex"
v-model="files"
#input-filter="inputFilter"
#input-file="inputFile"
ref="upload">
<i class="fa fa-plus"></i>
Select
</file-upload>
<div class="dropdown-menu">
<label class="dropdown-item" :for="name">Add files</label>
<a class="dropdown-item" href="#" #click="onAddFolder">Add folder</a>
<a class="dropdown-item" href="#" #click.prevent="addData.show = true">Add data</a>
</div>
</div>
<button type="button" class="btn btn-success" v-if="!$refs.upload || !$refs.upload.active" #click.prevent="$refs.upload.active = true">
<i class="fa fa-arrow-up" aria-hidden="true"></i>
Start Upload
</button>
<button type="button" class="btn btn-danger" v-else #click.prevent="$refs.upload.active = false">
<i class="fa fa-stop" aria-hidden="true"></i>
Stop Upload
</button>
</div>
</div>
<div class="option" v-show="isOption">
<div class="form-group">
<label for="accept">Accept:</label>
<input type="text" id="accept" class="form-control" v-model="accept">
<small class="form-text text-muted">Allow upload mime type</small>
</div>
<div class="form-group">
<label for="extensions">Extensions:</label>
<input type="text" id="extensions" class="form-control" v-model="extensions">
<small class="form-text text-muted">Allow upload file extension</small>
</div>
<div class="form-group">
<label>PUT Upload:</label>
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="radio" name="put-action" id="put-action" value="" v-model="putAction"> Off
</label>
</div>
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="radio" name="put-action" id="put-action" value="/upload/put" v-model="putAction"> On
</label>
</div>
<small class="form-text text-muted">After the shutdown, use the POST method to upload</small>
</div>
<div class="form-group">
<label for="thread">Thread:</label>
<input type="number" max="5" min="1" id="thread" class="form-control" v-model.number="thread">
<small class="form-text text-muted">Also upload the number of files at the same time (number of threads)</small>
</div>
<div class="form-group">
<label for="size">Max size:</label>
<input type="number" min="0" id="size" class="form-control" v-model.number="size">
</div>
<div class="form-group">
<label for="minSize">Min size:</label>
<input type="number" min="0" id="minSize" class="form-control" v-model.number="minSize">
</div>
<div class="form-group">
<label for="autoCompress">Automatically compress:</label>
<input type="number" min="0" id="autoCompress" class="form-control" v-model.number="autoCompress">
<small class="form-text text-muted" v-if="autoCompress > 0">More than {{$formatSize(autoCompress)}} files are automatically compressed</small>
<small class="form-text text-muted" v-else>Set up automatic compression</small>
</div>
<div class="form-group">
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" id="add-index" class="form-check-input" v-model="addIndex"> Start position to add
</label>
</div>
<small class="form-text text-muted">Add a file list to start the location to add</small>
</div>
<div class="form-group">
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" id="drop" class="form-check-input" v-model="drop"> Drop
</label>
</div>
<small class="form-text text-muted">Drag and drop upload</small>
</div>
<div class="form-group">
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" id="drop-directory" class="form-check-input" v-model="dropDirectory"> Drop directory
</label>
</div>
<small class="form-text text-muted">Not checked, filter the dragged folder</small>
</div>
<div class="form-group">
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" id="create-directory" class="form-check-input" v-model="createDirectory"> Create Directory
</label>
</div>
<small class="form-text text-muted">The directory file will send an upload request. The mime type is <code>text/directory</code></small>
</div>
<div class="form-group">
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" id="upload-auto" class="form-check-input" v-model="uploadAuto"> Auto start
</label>
</div>
<small class="form-text text-muted">Automatically activate upload</small>
</div>
<div class="form-group">
<button type="button" class="btn btn-primary btn-lg btn-block" #click.prevent="isOption = !isOption">Confirm</button>
</div>
</div>
<div :class="{'modal-backdrop': true, 'fade': true, show: addData.show}"></div>
<div :class="{modal: true, fade: true, show: addData.show}" id="modal-add-data" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Add data</h5>
<button type="button" class="close" #click.prevent="addData.show = false">
<span>×</span>
</button>
</div>
<form #submit.prevent="onAddData">
<div class="modal-body">
<div class="form-group">
<label for="data-name">Name:</label>
<input type="text" class="form-control" required id="data-name" placeholder="Please enter a file name" v-model="addData.name">
<small class="form-text text-muted">Such as <code>filename.txt</code></small>
</div>
<div class="form-group">
<label for="data-type">Type:</label>
<input type="text" class="form-control" required id="data-type" placeholder="Please enter the MIME type" v-model="addData.type">
<small class="form-text text-muted">Such as <code>text/plain</code></small>
</div>
<div class="form-group">
<label for="content">Content:</label>
<textarea class="form-control" required id="content" rows="3" placeholder="Please enter the file contents" v-model="addData.content"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" #click.prevent="addData.show = false">Close</button>
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
</div>
</div>
</div>
<div :class="{'modal-backdrop': true, 'fade': true, show: editFile.show}"></div>
<div :class="{modal: true, fade: true, show: editFile.show}" id="modal-edit-file" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Edit file</h5>
<button type="button" class="close" #click.prevent="editFile.show = false">
<span>×</span>
</button>
</div>
<form #submit.prevent="onEditorFile">
<div class="modal-body">
<div class="form-group">
<label for="name">Name:</label>
<input type="text" class="form-control" required id="name" placeholder="Please enter a file name" v-model="editFile.name">
</div>
<div class="form-group" v-if="editFile.show && editFile.blob && editFile.type && editFile.type.substr(0, 6) === 'image/'">
<label>Image: </label>
<div class="edit-image">
<img :src="editFile.blob" ref="editImage" />
</div>
<div class="edit-image-tool">
<div class="btn-group" role="group">
<button type="button" class="btn btn-primary" #click="editFile.cropper.rotate(-90)" title="cropper.rotate(-90)"><i class="fa fa-undo" aria-hidden="true"></i></button>
<button type="button" class="btn btn-primary" #click="editFile.cropper.rotate(90)" title="cropper.rotate(90)"><i class="fa fa-repeat" aria-hidden="true"></i></button>
</div>
<div class="btn-group" role="group">
<button type="button" class="btn btn-primary" #click="editFile.cropper.crop()" title="cropper.crop()"><i class="fa fa-check" aria-hidden="true"></i></button>
<button type="button" class="btn btn-primary" #click="editFile.cropper.clear()" title="cropper.clear()"><i class="fa fa-remove" aria-hidden="true"></i></button>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" #click.prevent="editFile.show = false">Close</button>
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
</div>
</div>
</div>
</div>
</template>
<script src='https://unpkg.com/vue#2.5.16/dist/vue.js'></script>
<script type="module">
import Cropper from 'cropperjs'
import ImageCompressor from '#xkeshi/image-compressor'
import { FileUpload } from "vue-upload-component";
</script>
<script>
new Vue({
el: '#vueUpload',
components: {
FileUpload,
},
data() {
return {
files: [],
accept: 'image/png,image/gif,image/jpeg,image/webp',
extensions: 'gif,jpg,jpeg,png,webp',
// extensions: ['gif', 'jpg', 'jpeg','png', 'webp'],
// extensions: /\.(gif|jpe?g|png|webp)$/i,
minSize: 1024,
size: 1024 * 1024 * 10,
multiple: true,
directory: false,
drop: true,
dropDirectory: true,
createDirectory: false,
addIndex: false,
thread: 3,
name: 'file',
postAction: '/upload/post',
putAction: '/upload/put',
headers: {
'X-Csrf-Token': 'xxxx',
},
data: {
'_csrf_token': 'xxxxxx',
},
autoCompress: 1024 * 1024,
uploadAuto: false,
isOption: false,
addData: {
show: false,
name: '',
type: '',
content: '',
},
editFile: {
show: false,
name: '',
}
}
},
watch: {
'editFile.show'(newValue, oldValue) {
// 关闭了 自动删除 error
if (!newValue && oldValue) {
this.$refs.upload.update(this.editFile.id, { error: this.editFile.error || '' })
}
if (newValue) {
this.$nextTick( () => {
if (!this.$refs.editImage) {
return
}
let cropper = new Cropper(this.$refs.editImage, {
autoCrop: false,
})
this.editFile = {
...this.editFile,
cropper
}
})
}
},
'addData.show'(show) {
if (show) {
this.addData.name = ''
this.addData.type = ''
this.addData.content = ''
}
},
},
methods: {
inputFilter(newFile, oldFile, prevent) {
if (newFile && !oldFile) {
// Before adding a file
// 添加文件前
// Filter system files or hide files
// 过滤系统文件 和隐藏文件
if (/(\/|^)(Thumbs\.db|desktop\.ini|\..+)$/.test(newFile.name)) {
return prevent()
}
// Filter php html js file
// 过滤 php html js 文件
if (/\.(php5?|html?|jsx?)$/i.test(newFile.name)) {
return prevent()
}
// Automatic compression
// 自动压缩
if (newFile.file && newFile.error === "" && newFile.type.substr(0, 6) === 'image/' && this.autoCompress > 0 && this.autoCompress < newFile.size) {
newFile.error = 'compressing'
const imageCompressor = new ImageCompressor(null, {
convertSize: 1024 * 1024,
maxWidth: 512,
maxHeight: 512,
})
imageCompressor.compress(newFile.file)
.then((file) => {
this.$refs.upload.update(newFile, { error: '', file, size: file.size, type: file.type })
})
.catch((err) => {
this.$refs.upload.update(newFile, { error: err.message || 'compress' })
})
}
}
if (newFile && newFile.error === "" && newFile.file && (!oldFile || newFile.file !== oldFile.file)) {
// Create a blob field
// 创建 blob 字段
newFile.blob = ''
let URL = (window.URL || window.webkitURL)
if (URL) {
newFile.blob = URL.createObjectURL(newFile.file)
}
// Thumbnails
// 缩略图
newFile.thumb = ''
if (newFile.blob && newFile.type.substr(0, 6) === 'image/') {
newFile.thumb = newFile.blob
}
}
// image size
// image 尺寸
if (newFile && newFile.error === '' && newFile.type.substr(0, 6) === "image/" && newFile.blob && (!oldFile || newFile.blob !== oldFile.blob)) {
newFile.error = 'image parsing'
let img = new Image();
img.onload = () => {
this.$refs.upload.update(newFile, {error: '', height: img.height, width: img.width})
}
img.οnerrοr = (e) => {
this.$refs.upload.update(newFile, { error: 'parsing image size'})
}
img.src = newFile.blob
}
},
// add, update, remove File Event
inputFile(newFile, oldFile) {
if (newFile && oldFile) {
// update
if (newFile.active && !oldFile.active) {
// beforeSend
// min size
if (newFile.size >= 0 && this.minSize > 0 && newFile.size < this.minSize) {
this.$refs.upload.update(newFile, { error: 'size' })
}
}
if (newFile.progress !== oldFile.progress) {
// progress
}
if (newFile.error && !oldFile.error) {
// error
}
if (newFile.success && !oldFile.success) {
// success
}
}
if (!newFile && oldFile) {
// remove
if (oldFile.success && oldFile.response.id) {
// $.ajax({
// type: 'DELETE',
// url: '/upload/delete?id=' + oldFile.response.id,
// })
}
}
// Automatically activate upload
if (Boolean(newFile) !== Boolean(oldFile) || oldFile.error !== newFile.error) {
if (this.uploadAuto && !this.$refs.upload.active) {
this.$refs.upload.active = true
}
}
},
alert(message) {
alert(message)
},
onEditFileShow(file) {
this.editFile = { ...file, show: true }
this.$refs.upload.update(file, { error: 'edit' })
},
onEditorFile() {
if (!this.$refs.upload.features.html5) {
this.alert('Your browser does not support')
this.editFile.show = false
return
}
let data = {
name: this.editFile.name,
error: '',
}
if (this.editFile.cropper) {
let binStr = atob(this.editFile.cropper.getCroppedCanvas().toDataURL(this.editFile.type).split(',')[1])
let arr = new Uint8Array(binStr.length)
for (let i = 0; i < binStr.length; i++) {
arr[i] = binStr.charCodeAt(i)
}
data.file = new File([arr], data.name, { type: this.editFile.type })
data.size = data.file.size
}
this.$refs.upload.update(this.editFile.id, data)
this.editFile.error = ''
this.editFile.show = false
},
// add folder
onAddFolder() {
if (!this.$refs.upload.features.directory) {
this.alert('Your browser does not support')
return
}
let input = document.createElement('input')
input.style = "background: rgba(255, 255, 255, 0);overflow: hidden;position: fixed;width: 1px;height: 1px;z-index: -1;opacity: 0;"
input.type = 'file'
input.setAttribute('allowdirs', true)
input.setAttribute('directory', true)
input.setAttribute('webkitdirectory', true)
input.multiple = true
document.querySelector("body").appendChild(input)
input.click()
input.onchange = (e) => {
this.$refs.upload.addInputFile(input).then(function() {
document.querySelector("body").removeChild(input)
})
}
},
onAddData() {
this.addData.show = false
if (!this.$refs.upload.features.html5) {
this.alert('Your browser does not support')
return
}
let file = new window.File([this.addData.content], this.addData.name, {
type: this.addData.type,
})
this.$refs.upload.add(file)
}
}
})
</script>
Assuming you're using Lian Yue's vue-upload-component and have installed it successfully, try removing the curly braces from your import:
import FileUpload from "vue-upload-component";
This will set FileUpload to the default export from vue-upload-component which I believe is what you want

Scroll to first error using Vue Validate in b-form

trying to scroll to the first error when submitting a form using Vue Validate for validation in bootstrap form (b-form)
I think you are looking for something like this-
const app = new Vue({
el:'#app',
data:{
errors:[],
name:null,
age:null,
movie:null
},
methods:{
checkForm:function(e) {
this.$refs.errorP.scrollIntoView();
if(this.name && this.age) return true;
this.errors = [];
if(!this.name) this.errors.push("Name required.");
if(!this.age) this.errors.push("Age required.");
e.preventDefault();
}
}
})
input,select {
margin-left: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<form id="app" #submit="checkForm" action="/something" method="post">
<div ref="errorP">
<p v-if="errors.length" >
<b>Please correct the following error(s):</b>
<ul>
<li v-for="error in errors">{{ error }}</li>
</ul>
</p>
</div>
<div style="height: 1000px;">
Scroll to the bottom to see the form
</div>
<p>
<label for="name">Name<label>
<input type="text" name="name" id="name" v-model="name">
</p>
<p>
<label for="age">Age<label>
<input type="number" name="age" id="age" v-model="age" min="0">
</p>
<p>
<label for="movie">Favorite Movie<label>
<select name="movie" id="movie" v-model="movie">
<option>Star Wars</option>
<option>Vanilla Sky</option>
<option>Atomic Blonde</option>
</select>
</p>
<p>
<input type="submit" value="Submit">
</p>
</form>
https://jsfiddle.net/anupdg/j24xt7rd/1/

On form button click success, form validations fire again

Hopefully this is a newbie question.
I am using Vuelidate to validate my form and the form validations works fine, when the “send email” button is clicked.However on success, instead of showing me the successful message, the system shows that all the form controls have errors(This is because I have bound the name, email, message controls to their corresponding empty data elements).
What am I missing?
How can I fix this issue?
Contact.vue
<template>
<div>
<section class="slice slice-lg" id="sct_contact_form">
<div class="container">
<div class="mb-5 text-center">
<span class="badge badge-soft-info badge-pill badge-lg">
Contact
</span>
<h3 class=" mt-4">Send us a message</h3>
</div>
<div class="row justify-content-center">
<div class="col-lg-8">
<form>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label class="form-control-label">Name</label>
<input class="form-control" type="text" placeholder="Name" v-model="user.name" id="name" name="name" :class="{ 'is-invalid': submitted && $v.user.name.$error }" >
<div v-if="submitted && !$v.user.name.required" class="invalid-feedback">Name is required</div>
</div>
</div>
</div>
<div class="row align-items-center">
<div class="col-md-12">
<div class="form-group">
<label class="form-control-label">Email</label>
<input class="form-control" type="email" placeholder="email#example.com"
v-model="user.email" id="email" name="email" :class="{ 'is-invalid': submitted && $v.user.email.$error }" >
<div v-if="submitted && $v.user.email.$error" class="invalid-feedback">
<span v-if="!$v.user.email.required">Email is required</span>
<span v-if="!$v.user.email.email">Email is invalid</span>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label class="form-control-label">Message</label>
<textarea class="form-control" data-toggle="autosize" placeholder="Tell us a few words ..." rows="3" style="overflow: hidden; overflow-wrap: break-word; resize: none; height: 96.9922px;"
v-model="user.message" id="message" name="message" :class="{ 'is-invalid': submitted && $v.user.message.$error }" ></textarea>
<div v-if="submitted && $v.user.message.$error" class="invalid-feedback">
<span v-if="!$v.user.message.required">Message is required</span>
<span v-if="!$v.user.message.minLength">Message must be at least 6 characters</span>
</div>
</div>
</div>
</div>
<div class="text-center mt-4">
<button type="button" class="btn btn-dark rounded-pill" v-on:click="SendEmail()">Send your message</button>
<span class="d-block mt-4 text-sm">We'll get back to you in 24-48 h.</span>
<div v-if="submitted" class="valid-feedback">
<span v-if="!$v.user.name.$error && !$v.user.email.$error && !$v.user.message.$error">Your email was send successfully. We'll get back to you in 24-48 h.</span>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
</div>
</template>
import { Email } from '../api/email.js';
import { required, email, minLength, sameAs } from "vuelidate/lib/validators";
export default {
name: "Contact",
components:{
},
data() {
return {
user: {
name: "",
email: "",
message: ""
},
submitted: false
};
},
validations: {
user: {
name: { required },
email: { required, email },
message: { required, minLength: minLength(6) }
}
},
methods: {
SendEmail() {
this.submitted = true;
this.$v.$touch();
if (this.$v.$invalid) {
return;
}
var nameWithEmailText="Email message from: "+ this.user.name + "\nEmail message: " + this.user.message;
var subject="Email from contact us page in common membership website";
Meteor.call('email.send', this.user.email, subject, nameWithEmailText);
this.user.name='';
this.user.email='';
this.user.message='';
}
}
}
You should wait for the Meteor.call() to complete, then reset the validation state.
For example
Meteor.call('email.send', this.user.email, subject, nameWithEmailText, (error, result) => {
this.user.name = ''
this.user.email = ''
this.user.message = ''
this.$v.$reset()
})

Not entering the created record in the list form in Angular 5

In my home page i have to create records and when i am creating the records and clicking on submit button and getting like added successfully. After that the created record is not available in the list records.When i'm creating another new record and submit it the previous created record is displays in the list.
Type Script code is:
import { Component, OnInit } from '#angular/core';
import {FormControl, Validators, NgForm } from '#angular/forms';
import { VisitService } from '../shared/visit.service';
import { ToastrService } from 'ngx-toastr';
import { Response, RequestOptions, Http, Headers } from '#angular/http';
import { CookieService } from 'ngx-cookie-service';
#Component({
selector: 'app-visit',
templateUrl: './visit.component.html',
styleUrls: ['./visit.component.css']
})
export class VisitComponent implements OnInit {
cookieValue = 'UNKNOWN';
constructor(private visitService: VisitService,private http: Http,private cookieService: CookieService, private toastr: ToastrService ) { }
ngOnInit() {
this.resetForm();
this.cookieValue = this.cookieService.get('session');
console.log('token from browser' + this.cookieValue );
const url = `http://localhost:8080//api/getallvisits/`;
// const headers = new Headers({'Content-Type': 'application/json','Authorization':'Bearer' +this.cookieValue});
let headers = new Headers({ 'Authorization': 'Bearer ' + this.cookieValue });
// const headers = new Headers();
// headers.append('Authorization', 'Bearer' +this.cookieValue );
const options = new RequestOptions({ headers: headers });
return this.http.get(url, options)
.subscribe(res => {
console.log('message from' + res);
// this.refresh();
alert('successfullyyy...');
// console.log('message from' + people.json())
});
}
resetForm(form?: NgForm) {
if (form != null)
form.reset();
this.visitService.selectedVisit = {
'ID':null,
'UserName': '',
'Height': null,
'Weight': null,
'Temperature': null,
'BloodPressure': '',
'PatientNote': '',
'NurseNote': '',
'DoctorNote': '',
}
}
onSubmit(form: NgForm) {
if (form.value.ID == null) {
this.visitService.createVisit(form.value)
.subscribe(data => {
this.resetForm(form);
this.visitService.getVisitList();
this.toastr.success('New Record Added Succcessfully', 'Employee Register');
})
}
else {
this.visitService.updateVisit(form.value.ID, form.value)
.subscribe(data => {
this.resetForm(form);
this.visitService.getVisitList();
this.toastr.info('Record Updated Successfully!', 'Employee Register');
});
}
}
}
And my HTML page is:
<form class="visit-form" #visitForm="ngForm" (ngSubmit)="onSubmit(visitForm)">
<input type="hidden" name="ID" #ID="ngModel" [(ngModel)]="visitService.selectedVisit.ID">
<div class="form-row">
<div class="form-group col-md-6">
<mat-form-field class="example-full-width">
<input class="form-control" matInput placeholder="UserName" name="UserName" #UserName="ngModel" [(ngModel)]="visitService.selectedVisit.username"
placeholder="User Name" required>
<div class="validation-error" *ngIf="UserName.invalid && UserName.touched">This Field is Required.</div>
</mat-form-field>
</div>
<div class="form-group col-md-6">
<mat-form-field class="example-full-width">
<input class="form-control" matInput placeholder="Height" name="Height" #Height="ngModel" [(ngModel)]="visitService.selectedVisit.height" placeholder="Height"
required>
<div class="validation-error" *ngIf="Height.invalid && Height.touched">This Field is Required.</div>
</mat-form-field>
</div>
</div>
<div class="form-group">
<mat-form-field class="example-full-width">
<input class="form-control" matInput placeholder="Temperature" name="Temperature" #Temperature="ngModel" [(ngModel)]="visitService.selectedVisit.temperature" placeholder="Temperature">
</mat-form-field>
</div>
<div class="form-group">
<mat-form-field class="example-full-width">
<input class="form-control" matInput placeholder="Weight" name="Weight" #Weight="ngModel" [(ngModel)]="visitService.selectedVisit.weight" placeholder="Weight">
</mat-form-field>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<mat-form-field class="example-full-width">
<input class="form-control" matInput placeholder="Blood Pressure" name="BloodPressure" #BloodPressure="ngModel" [(ngModel)]="visitService.selectedVisit.bloodpressure" placeholder="Blood Pressure">
</mat-form-field>
</div>
<div class="form-group col-md-6">
<mat-form-field class="example-full-width">
<input class="form-control" matInput placeholder="Patient Note" name="PatientNote" #PatientNote="ngModel" [(ngModel)]="visitService.selectedVisit.patientnote" placeholder="Patient Note">
</mat-form-field>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<mat-form-field class="example-full-width">
<input class="form-control" matInput placeholder="Nurse Note" name="NurseNote" #NurseNote="ngModel" [(ngModel)]="visitService.selectedVisit.nursenote" placeholder="Nurse Note">
</mat-form-field>
</div>
<div class="form-group col-md-6">
<mat-form-field class="example-full-width">
<input class="form-control" matInput placeholder="Doctor Note" name="DoctorNote" #DoctorNote="ngModel" [(ngModel)]="visitService.selectedVisit.doctornote" placeholder="Doctor Note">
</mat-form-field>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-8">
<button [disabled]="!visitForm.valid" type="submit" class="btn btn-lg btn-block btn-info">
<i class="fa fa-floppy-o"></i> Submit</button>
</div>
<div class="form-group col-md-4">
<button type="button" class="btn btn-lg btn-block btn-secondary" (click)="resetForm(visitForm)">
<i class="fa fa-repeat"></i> Reset</button>
</div>
</div>
</form>
Anyone please refer that.Thank You
See if you are displaying the value in html table or like that then after submit you have to destroy the table .
and again Reinit the table then only it will display the current added value as well.
So You can do that or else call the onload function when submit function ends .
or if you have some other issue then let me know in details.

Vue.js not updating template when changing child objects

I'm extending laravel spark and wanted to try to validate registration before actually sending it off.
All data is handled nicely and correctly from the server but the errors do not pop-up.
The code being used for validation is as following:
module.exports = {
...
methods: {
...
validate(field, value) {
var formData = {
field: field,
value: value
};
var form = new SparkForm(formData);
Spark.post('/register_validate', form).then(response => {
this.registerForm.addSuccess(field);
}).catch(errors => {
this.registerForm.addError(field, errors[field]);
});
}
}
};
After, i extended SparkForm and added these methods (successes is just a copy of errors, used to display validation success messages):
/**
* SparkForm helper class. Used to set common properties on all forms.
*/
window.SparkForm = function (data) {
...
this.addError = function(field, errors) {
form.successes.remove(field);
form.errors.add(field, errors);
},
this.addSuccess = function(field) {
form.errors.remove(field);
form.successes.add(field, true);
}
};
And finally i added some methods on the SparkFormErrors.
/**
* Spark form error collection class.
*/
window.SparkFormErrors = function () {
...
this.add = function(field, errors) {
this.errors[field] = errors;
};
this.remove = function(field) {
delete this.errors[field];
}
};
In the console no errors are shown and in the network tab i can see the correct messages coming true, also when i add a console log in for example the response callback i can see the actual errors or success messages. But they are not drawn on screen.
For completeness i'll include the important content of the template blade file:
#extends('spark::layouts.app')
#section('content')
<spark-register-stripe inline-template>
<!-- Basic Profile -->
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">
{{ trans('auth.register.title') }}
</div>
<div class="panel-body">
<!-- Generic Error Message -->
<div class="alert alert-danger" v-if="registerForm.errors.has('form')">
#{{ registerForm.errors.get('form') }}
</div>
<!-- Registration Form -->
<form class="form-horizontal" role="form">
<!-- Name -->
<div class="form-group" :class="{'has-error': registerForm.errors.has('name')}">
<label class="col-md-4 control-label">{{ trans('user.name') }}</label>
<div class="col-md-6">
<input type="name" class="form-control" name="name" v-model="registerForm.name" autofocus #blur="validate('name', registerForm.name)">
<span class="help-block" v-show="registerForm.errors.has('name')">
#{{ registerForm.errors.get('name') }}
</span>
</div>
</div>
<!-- E-Mail Address -->
<div class="form-group" :class="{'has-error': registerForm.errors.has('email')}">
<label class="col-md-4 control-label">{{ trans('user.email') }}</label>
<div class="col-md-6">
<input type="email" class="form-control" name="email" v-model="registerForm.email" #blur="validate('email', registerForm.email)">
<span class="help-block" v-show="registerForm.errors.has('email')">
#{{ registerForm.errors.get('email') }}
</span>
</div>
</div>
<!-- Password -->
<div class="form-group" :class="{'has-error': registerForm.errors.has('password')}">
<label class="col-md-4 control-label">{{ trans('user.password') }}</label>
<div class="col-md-6">
<input type="password" class="form-control" name="password" v-model="registerForm.password" #blur="validate('password', registerForm.password)">
<span class="help-block" v-show="registerForm.errors.has('password')">
#{{ registerForm.errors.get('password') }}
</span>
</div>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-4">
<button class="btn btn-primary" #click.prevent="register" :disabled="registerForm.busy">
<span v-if="registerForm.busy">
<i class="fa fa-btn fa-spinner fa-spin"></i>{{ trans('auth.register.submitting') }}
</span>
<span v-else>
<i class="fa fa-btn fa-check-circle"></i>{{ trans('auth.register.submit') }}
</span>
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</spark-register-stripe>
#endsection
Any bright mind seeing what i'm missing/forgetting?