According to the docs, I'm under the impression that vuelidate should automatically add internal nested validations into the global validation state. And it does work when using the options api. However, I'm unable to make it work when using the composition api.
I've built small demo sample to illustrate the issue. The initial page looks like this:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Basic Vue template</title>
<meta name="description" content="A simple Vue.js Template for new demo code.">
<meta name="author" content="Luis Abreu">
<script src="js/vue.global.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-demi"></script>
<script src="https://cdn.jsdelivr.net/npm/#vuelidate/core"></script>
<script src="https://cdn.jsdelivr.net/npm/#vuelidate/validators"></script>
</head>
<body>
<h1>
Hello world!
</h1>
<div id="app">
<input type="text" v-model.trim="name">
<br>
<br>
<br>
<div v-for="(b, pos) in branches">
<branch :current-Branch="b" />
</div>
<br>
<div>
{{ v$.$invalid}}
<br>
{{ v$.$error.$messages}}
</div>
</div>
<script type="module">
const {createApp, ref} = Vue;
const { minLength } = VuelidateValidators;
const { useVuelidate } = Vuelidate;
import branch from './branch.js';
const name = ref('Hi, there!');
const branches = ref([
{name: 'Filial 1', representative: ''},
{name: 'Filial 2', representative: 'John'}
]);
const branchesRules = computed( () => ({
branches: {
minLength: 1
}
}));
const v$ = useVuelidate(branchesRules, {branches});
const app = createApp({
setup(){
return {
name,
branches,
v$
};
}
});
app.component('branch', branch);
app.mount('#app');
</script>
</body>
</html>
And here's the component exported by the branch.js file:
const { required } = VuelidateValidators;
const { useVuelidate } = Vuelidate;
const { ref, computed, onMounted } = Vue;
const rules = computed( () => ({
branch: {
name: {required}
}
}));
export default {
props:['currentBranch'],
setup(props, ctx) {
const branch = ref(props.currentBranch);
const v$ = useVuelidate(rules, { branch });
return {
branch,
v$
};
},
template: `
<div>
<input type="text"
#input="v$.branch.name.$touch"
#blur="v$.branch.name.$touch"
v-model.trim="branch.name" />
<br>
<input type="text"
v-model.trim="branch.representative" />
<br><br><br><br>
</div>
`
}
Whenever I test the page, I can see that the component validation rule is working, but it's no being propagated to the top level component:
I'm surelly missing something, but what?
Related
I'm using QUASAR and I want to get the state of my q-checkbox whether if it's checked or not. I've used event.target.checked and event.target.value but they are all undefined.
my checkbox:
<q-checkbox
v-on:click="addServices(full_service, $event)"
v-model="form.selected_full_services"
:val="full_service" />
my method:
addServices(full_service, event) {
console.log(event.target.checked)
console.log(event.target.value)
}
console:
output undefined
If I understood you correctly, maybe you don't need function at all :
const { ref } = Vue
const app = Vue.createApp({
setup () {
const full_services = ref( ['aaa', 'bbb', 'ccc'] )
const form = ref( { selected_full_services: [] } )
return { form, full_services }
}
})
app.use(Quasar)
app.mount('#q-app')
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet" type="text/css">
<link href="https://cdn.jsdelivr.net/npm/quasar#2.10.1/dist/quasar.prod.css" rel="stylesheet" type="text/css">
<div id="q-app">
{{form}}
<div v-for="full_service in full_services">
<q-checkbox
:label="full_service"
v-model="form.selected_full_services"
:val="full_service" />
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#3/dist/vue.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/quasar#2.10.1/dist/quasar.umd.prod.js"></script>
I'm a beginner in VUE, I have programmed code that, after loading the web pages, downloads the data from json and renders it to wonder with the id "app".
However, I need the data to be loaded not at the beginning, but only after clicking the button.
Thank you very much for the tips and advice.
const app = new Vue ({
el: '#app',
data: {
urlPrefix: '',
newName: '',
newDescription: '',
newExperts_advice: '',
newProduct_benefit_2: '',
newImage: '',
characters: [{
}
],
},
methods: {
add() {
this.characters.push ({
name: this.newName,
description: this.newDescription,
experts_advice: this.newExperts_advice,
product_benefit_2: this.newProduct_benefit_2,
image: this.newImage,
})
}
},
created: function(){
fetch('./data.json')
.then(res => res.json())
.then(json => this.characters = json)
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TEST</title>
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.12/dist/vue.js"></script>
<link rel="icon" href="favicon.ico" type="image/x-icon"/>
</head>
<body>
<div id="app">
<button>Fetch data</button>
<div class="info-v1" v-for="item in characters">
<section class="head">
<h2>{{ item.name }}</h2>
<p> {{ item.description }}</p>
</section>
<section class="body">
<img v-bind:src="urlPrefix + item.image " />
<h3>{{ item.product_benefit_2 }}</h3>
<p>{{ item.experts_advice }}</p>
</section>
</div>
</div>
</body>
</html>
First you should create method in methods to fetch your data.
methods: {
yourNewMethodToFetchData() {
fetch('./data.json')
.then(res => res.json())
.then(json => this.characters = json)
}
}
Second add click event to your fetch data button like this:
<button #click="yourNewMethodToFetchData">Fetch data</button>
Lastly remove fetch code from created hook:
created: function(){
}
I am trying to implement a Vue Component with a custom render function.
As soon as my template has nested HTML elements, i get this error:
TypeError: this.$options.staticRenderFns is undefined
How do I implement staticRenderFns?
Code:
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<comp temp="temp1"></comp>
</div>
<script>
var myTemplates = new Array();
myTemplates['temp1'] = Vue.compile("<div><div>This template will come from an AJAX source</div></div>").render;
var Comp = {
props: ["temp"],
data() {
return {
renderFunc: myTemplates[ this.$props.temp ],
}
},
render(h) {
return this.renderFunc()
}
};
new Vue({
el: "#app",
data: { },
components: { Comp }
});
</script>
</body>
</html>
Using Vue.js, how do you use axios GET to display the response in a dialog?
I've tried the following:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<template>
<label>Protocol</label> Display protocol details from json
<div class="text-xs-center">
<br>
</div>
</template>
<script>
export default {
dialog3: false
created() {
let self = this
axios.get('http://localhost:4000/ap/device')
.then(function(response) {
self.fDModelName(response.data.result)
console.log(JSON.stringify(response.data.result))
})
},
methods: {
fDModelName: function(message) {
console.log("inside")
}
}
}
</script>
</body>
</html>
Create a data object where you have content as a key. On component created, you can assign it to the component's content value.
<template>
<div>
{{ content }}
</div>
</template>
<script>
export default {
data () {
return {
content: []
}
},
created () {
axios.get('http://localhost:4000/ap/device')
.then(function (response) {
this.content = response.data.result
})
}
}
</script>
I am a fresher.I try to use scope slot and directive to create a list sample ,the code follow:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>作用域插槽</title>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
</head>
<body>
<div id="app">
<app></app>
</div>
</body>
<script>
Vue.directive("selectall",{
bind:function(el,binding,vnode,oldVnode){
var arg = binding.arg,
value = binding.value;
console.log(arg,value);
$(el).on('change',function(){
});
}
});
Vue.component("list",{
template:"<div><ul>"
+"<slot name='item' v-for='item in litodos' :text= 'item.text' :time='item.time' :idx='item.idx'></slot>"
+"</ul>"
+"</div>",
props:['litodos'],
data:function(){
return {
message:"list-message"
}
}
});
Vue.component("app",{
template:"<div class='container'>"
+" <input type='checkbox' v-selectall:parent='group1'/>select all gruop1"
+"<list :litodos='todos1'>"
+"<template slot='item' scope='props'>"+
+"<li><input type='checkbox' value='{{props.idx}}' v-selectall:child='group1'/>{{props.text}} </li>"
+"</template>"
+"</list>"
+" <hr><input type='checkbox' v-selectall:parent='group2'/>select all gruop2"
+"<list :litodos='todos2'>"
+"<template slot='item' scope='props'>"+
+"<li><input type='checkbox' value='{{props.idx}}' v-selectall:child='group2'/>{{props.text}}</li>"
+"</template>"
+"</list>"
+"</div>",
data:function(){
return {
group1:"group1",
group2:"group2",
todos1:[
{
text:'study english',
time:'3hour',
idx:'1'
},{
text:'study vue',
time:'2hour',
idx:'2'
}
],
todos2:[
{
text:'学英语',
time:'3hour',
idx:'3'
},{
text:'学js',
time:'2hour',
idx:'4'
}
]
};
}
})
var app = new Vue({
el: '#app',
data:{}
});
</script>
</html>
and here are essential fragment:
+"<list :litodos='todos1'>"
+"<template slot='item' scope='props'>"+
+"<li><input type='checkbox' value='{{props.idx}}' v-selectall:child='group1'/>{{props.text}} </li>"
+"</template>"
+"</list>"
but the result is like this:
enter image description here
I find out that the slot return to NaN,so I am so confused.Can you help me find the keys point to resolve this bug?Thank you!