I'm trying to do something like this, do not know how to describe in technical term, can't seem to find a solution for this.
<div id="app">
<input type="text" v-model="model1" />
</div>
<div>
<div id="model2">ABCDEFG</div>
<input type="text" />
</div>
<script>
new Vue({
el: '#app',
data: {'model1': 'value'},
...
...
...
});
</script>
How can i add model2 element into my #app data? I do not want to wrap my model2 inside of #app because it is a partial, and is shared throughout the application. Is there a way i can inject it on a particular page when it is needed?
You can make that model2 div a separate component o that it can be reused anywhere you want like this:
html
<div id="app">
<input type="text" v-model="model1" />
<reusable-comp></reusable-comp>
</div>
script
<script>
var reusableComp = {
template: `
<div id="model2">
<div>ABCDEFG</div>
<input type="text" />
</div>
`,
data(){
return{
//reactive properties for this component
}
}
}
new Vue({
el: '#app',
data: {'model1': 'value'},
components:{
reusableComp
}
...
...
...
});
</script>
You can also register that as a global component like this
Vue,.component('reusableComp',{ //...options })`
See docs for more on components
Related
hi im using vuejs with laravel project
and this is my vuejs code
Vue.component('search_and_select',{
template:
'<div>'+
'<slot :test_text="test_text"></slot>'+
'</div>',
data:function(){
return {
test_text:"test text",
}
},
methods:{
},
props:{
},
});
new Vue({
el:'.user_search_and_select',
data:{
},
});
and this is my html code
<div is='search_and_select'>
<div slot-scope="{test_text}">
#{{test_text}}
<input type='text' v-model='test_text' />
</div>
</div>
till now everything working so good
but if i keyup <input type='text' v-model='test_text' /> the test_text dont change still the same
so how can i change in slot and change in parent component too
thanks a lot ..
You have to expose a method to the slot for updating the value. This means you won't be able to use v-model because you will need to handle :value and #input separately now.
<slot :test_text="test_text" :update_test_text="update_test_text"></slot>
methods: {
update_test_text(value) {
this.test_text = value
}
}
Now you can use the component like this:
<search_and_select>
<div slot-scope="{ test_text, update_test_text }">
<input
type="text"
:value="test_text"
#input="update_test_text($event.target.value)"
>
</div>
</search_and_select>
Vue.js v2.6.11 / vee-validate v3.2.2
I have a button that will push new element to form.demand (data in vue app) on click event.
And if form.demand update, html in v-for should be updated.
After I wrap it in vee-validate component , it not works.
form.demand will update, but v-for won't.
I try to put same html in test-component, when form.demand update, v-for update too.
I can't figure out why...
following is my code:
HTML
<div id="content">
<test-component>
<div v-for="demand in form.demand">{{demand}}</div>
</test-component>
<validation-provider rule="" v-slot="v">
<div #click="addDemand">new</div>
<div v-for="(demand,index) in form.demand">
<div>{{demand.name}}</div>
<div>{{demand.count}}</div>
<input type="text" :name="'demand['+index+'][name]'" v-model="form.demand[index].name" hidden="hidden" />
<input type="text" :name="'demand['+index+'][count]'" v-model="form.demand[index].count" hidden="hidden" />
</div>
</validation-provider>
</div>
javascript
Vue.component('validation-provider', VeeValidate.ValidationProvider);
Vue.component('validation-observer', VeeValidate.ValidationObserver);
Vue.component('test-component',{
template: `
<div>
<slot></slot>
</div>
`
})
var app = new Vue({
el: "#content",
data: {
form: {
demand: [],
},
},
methods: {
addDemand(){
this.form.demand.push({
name : "demand name",
count: 1
})
}
})
------------Try to use computed & Add :key----------------
It's still not work. I get same result after this change.
HTML
<validation-provider rule="" v-slot="v">
<div #click="addDemand">new</div>
<div v-for="(demand,index) in computed_demand" :key="index">
<!--.........omitted.........-->
</validation-provider>
Javascript
var app = new Vue({
el: "#content",
// .......omitted
computed:{
computed_demand() {
return this.form.demand;
}
},
})
I think I found the problem : import Vue from two different source. In HTML, I import Vue from cdn. And import vee-validate like following:
vee-validate.esm.js
import Vue from './vue.esm.browser.min.js';
/*omitted*/
validator.js
import * as VeeValidate from './vee-validate.esm.js';
export { veeValidate };
main.js
// I didn't import Vue from vue in this file
import { veeValidate as VeeValidate } from './validator.js';
Vue.component('validation-provider', VeeValidate.ValidationProvider);
HTML
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<!-- at end of body -->
<script src="/static/javascripts/main.js" type="module"></script>
</body>
After I fix this( import vee-validate from cdn, or import Vue by ES6 module).
It works, although it still have infinite loop issue with vee-validate.
Sorry for I didn't notice that import vue from two different source.
Please provide a key in you v-for. see code below
<div v-for="(demand,index) in form.demand" :key="index">
<div>{{demand.name}}</div>
<div>{{demand.count}}</div>
<input type="text" :name="'demand['+index+'][name]'" v-model="form.demand[index].name" hidden="hidden" />
<input type="text" :name="'demand['+index+'][count]'" v-model="form.demand[index].count" hidden="hidden" />
</div>
Or, make a computed property that will hold your form.demands array, like this one
computed: {
form_demands: function() {
return this.form.demand
}
}
then call this computed property in your v-for
<div v-for="(demand,index) in form_demands" :key="index">
<div>{{demand.name}}</div>
<div>{{demand.count}}</div>
<input type="text" :name="'demand['+index+'][name]'" v-model="form.demand[index].name" hidden="hidden" />
<input type="text" :name="'demand['+index+'][count]'" v-model="form.demand[index].count" hidden="hidden" />
</div>
Or, use the vue forceUpdate method
import Vue from 'vue';
Vue.forceUpdate();
Then in your component, just call the method after you add demand
this.$forceUpdate();
It is recommended to provide a key with v-for whenever possible,
unless the iterated DOM content is simple, or you are intentionally
relying on the default behavior for performance gains.
I have a simple problem but I can't find any reliable answer.
So here is what I want to do. The code is simplified for clarity.
<h1>Hello</h1>
<div id='app'>
<template>
<p>Here is the app: {{message}}</p>
#Html.Partial("_Component")
</template>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
message: "App works!"
}
});
</script>
And _Component.cshtml file:
<my-component inline-template>
<div>
<p><button v-on:click="counter += 1">Add One More Click</button></p>
<p>The button has been clicked {{ counter }} times</p>
</div>
</my-component>
<script>
Vue.component('my-component',
{
data: function () {
return {
counter: 1
}
}
});
</script>
Problem with this code is that my-component is not rendering. Overall, I'm working in project of asp.net mvc application and its required to use template tag.
If I remove this tag, the page is a mess until it's rendered.
Is there any solution or workaround to be able to see component in this case?
You declare the component in the wrong place. Should be like this
<h1>Hello</h1>
<div id='app'>
<template>
<p>Here is the app: {{message}}</p>
<my-component inline-template>
<div>
<p><button v-on:click="counter += 1">Add One More Click</button></p>
<p>The button has been clicked {{ counter }} times</p>
</div>
</my-component>
</template>
</div>
<script>
Vue.component('my-component', {
data: function () {
return {
counter: 1
}
}
});
var vm = new Vue({
el: '#app',
data: {
message: "App works!"
}
});
</script>
I started using vuejs with parcel. I have a main component App.vue from which I call a subcomponent Hello.vue using <Hello/> in App's template. I have a weird bug if I don't put the <Hello/> inside a div tag, everything that comes after in html doesn't show. The code is below:
index.js
import Vue from "vue";
import App from "./App";
new Vue({
el: "#app",
components: { App },
template: "<App/>"
});
App.vue
<template>
<div id="app">
<h3>bla bla</h3>
<div><Hello/></div>
<!-- if not put inside a div, hides everything after-->
<h2>test</h2>
<p>kldsfnlkdsjfldsfds</p>
<h5>skjdnsqkfdnlkdsqf</h5>
</div>
</template>
<script>
import Hello from "./components/Hello";
export default {
name: "App",
components: {
Hello
}
};
</script>
<style>
</style>
Hello.vue
<template>
<div>
<h1>{{ message }}</h1>
<h2>Hello {{ person.firstname}} {{person.lastname}}</h2>
<label>
Firstname:
<input type="text" v-model="person.firstname">
</label>
<label>
Lastname:
<input type="text" v-model="person.lastname">
</label>
<label>
Message:
<input type="text" v-model="message">
</label>
</div>
</template>
<script>
export default {
data() {
return {
person: {
firstname: "John",
lastname: "Doe"
},
message: "Welcome !"
};
}
};
</script>
<style>
</style>
Here is a screenshot of what I get without wrapping <Hello/> with a <div></div>
And then with a div:
Thanks !
EDIT: I don't get an error in the console. I forgot to add that I tried with webpack and I don't get this bug, so It's most likely related to parcel.
Some browsers do not display elements correctly if they use <foo /> without a closing tag, instead of <foo></foo>.
If items are not rendered with the closing tag, this may be your issue.
Some vue components will generate the closing tag from your template, even though you do not have it in your source, and others will not.
When you use a SFC (Single File Component) you must have only one element inside the <template>. Then, inside that one element you can have as many other elements as you like.
Have a look at the "Example sandbox" Simple to do app in the official documentation: https://v2.vuejs.org/v2/guide/single-file-components.html#Example-Sandbox
The file ToDoList.vue is a good example in here: https://codesandbox.io/s/o29j95wx9
I get my data via AJAX from the Vue instance, and I need to pass that data to the components. I am now learning how Vue.js works, but I find the documentation a little fragmentary...
Here is aproximately my code:
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<title>mysite</title>
</head>
<body>
<div id="app">
<parent-component></parent-component>
</div>
<template id="parent-component-template">
<div id="the-template">
<div class="the-list">
<span is="sector-item" v-for="item in sectors" :sector="item"></span>
</div>
<button>Button</button>
</div>
</template>
<template id="sector-item-template">
<span>
{{ sector.name }}
</span>
</template>
<!-- Vue.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<script>
Vue.component('parent-component', {
template: '#parent-component-template'
});
Vue.component('sector-item', {
props: ['sector'],
template: '#sector-item-template'
});
let app = new Vue({
el: '#app',
data: {
sectors: [{
'id': 1,
'name': 'Industry'
}]
}
});
</script>
</body>
</html>
I get the following error:
[Vue warn]: Property or method "sectors" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
Where do I make a mistake?
I think your code is not complete. I tried to simulate what you trying to, in the snippet bellow:
Vue.component('parent-component', {
props: ['sectors']
});
Vue.component('child-component', {
props: ['item']
});
new Vue({
el: '#app',
data: {
sectors: [
{
'id': 1,
'name': 'Industry'
},
{
'id': 2,
'name': 'Education'
}
]
}
});
.the-list > div {
padding: 5px;
border: 1px solid gray;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<div id="app">
<parent-component :sectors="sectors" inline-template>
<div class="the-list">
<child-component :item="sector" :key="sector.id" v-for="sector in sectors" inline-template>
<div>
<span v-text="item.name"></span>
<button>Button</button>
</div>
</child-component>
</div>
</parent-component>
</div>
The Vue instance owns the property sectors and I passed this property as a prop to the <parent-component>.
Now <parent-component> has a prop called sectors(it could be another name) that received the value of sectors from the main Vue instance. I've used v-for to iterate over all items of the parent-component prop passing each item of the array to the <child-component>.
The <child-component> has a prop called item in which I passed the value of each element of the array.
You can learn more, here for free.
I hope this answer can be helpful.