I'm trying to get data from parent component and use them in child component v-bind:style.
Here's my code.
<body>
<div id="parentComponent">
<child-component v-bind:propsdata="parentBackground" v-bind:propsdata2="parentFontstyle"></child-component>
</div>
<script>
Vue.component('child-component', {
props: ['propsdata', 'propsdata2'],
data: function() {
return {
childBackground: this.propsdata,
childFontStyle: this.propsdata2
},
template: '<p v-bind:style="childBackgroundColor, childFontStyle">Child componnent Area</p>'
});
new Vue ({
el: '#parentComponent',
data: function() {
return {
parentBackground: 'background-color:yellow;',
parentFontStyle: 'font-style: italic;'
},
})
</body>
When I run this code, only second style(childFontStyle) is applied to Child componnent template.
I also tried v-bind:style="[childBackgroundColor, childFontStyle]" and doesn't work.
Is there any way to apply both style?
You need to pass the props property as an object and can able to bind the props directly to the child. You have some typo mistakes that need to be fixed as well. Here is the working snippet.
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="parentComponent">
<child-component v-bind:propsdata="parentBackground" v-bind:propsdata2="parentFontStyle"></child-component>
</div>
<script>
Vue.component("child-component", {
template: `<p v-bind:style="[propsdata, propsdata2]">Child componnent Area</p>`,
props: ["propsdata", "propsdata2"]
});
new Vue({
el: "#parentComponent",
data: function() {
return {
parentBackground: {
"background-color": "yellow"
},
parentFontStyle: {
"font-style": "italic"
}
};
}
});
</script>
</body>
</html>
I wish to use Vue.js in a multi-page environment. For this project I can't use webpack or the vue.cli. I have to use basic ways of importing the various libraries and then using them. I'm nearly there but I can't figure out how I can import components. I'm assuming I need to use require.js but I don't know enough to proceed.
This is the main component (index.html):
<!DOCTYPE html>
<html lang='en' class=''>
<head>
<meta charset='UTF-8'><meta name="robots" content="noindex">
<title>Hello</title>
</head><body>
<div id="app">
<p>Hello this is the {{results}} app</p>
<br /><br />
<p>Now it's time for a component to be shown:</p>
<app-my-accordion></app-my-accordion>
</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js'></script>
<script src='require.js'></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
import MyAccordion from 'components/my-accordion.html'; // <--Problem here
new Vue({
el: '#app',
components: {
'app-my-accordion': MyAccordion
},
data() {
return {
results: null
}
},
mounted() {
axios.get("http://myApi")
.then(response => { this.results = response.data.name; console.log(response.data.name); })
}
});
</script>
</body></html>
And then in my my-accordion.html
<template>
<div>And my child's component name is: {{results}}</div>
</template>
<script>
export default {
data() {
return {
results: null
}
},
mounted: function () {
axios.get("http://myOtherApi")
.then(response => { this.results = response.data.name; console.log(response.data.name); })
}
}
</script>
</body></html>
I'm new to vue js.
I'm just creating a simple project where I just include vuejs through CDN. not using node/npm or cli.
I keep all my html markup in single html which looks messy as it grows. I tried to split html to views and want to include it by something analogous to ng-include of angularJs
I have worked in angular previously where there is ng-include to load external html files. I'm looking for something similar to that in vue. the whole point is to split my html files into more maintainable separate files.
have come across <template src="./myfile.html"/> but it doesn't work
Can somebody help me out
It's actually remarkably easy, but you need to keep something in mind. Behind the scenes, Vue converts your html template markup to code. That is, each element you see defined as HTML, gets converted to a javascript directive to create an element. The template is a convenience, so the single-file-component (vue file) is not something you'll be able to do without compiling with something like webpack. Instead, you'll need to use some other way of templating. Luckily there are other ways of defining templates that don't require pre-compiling and are useable in this scenario.
1 - string/template literals
example: template: '<div>{{myvar}}</div>'
2 - render function 🤢
example: render(create){create('div')}
Vue has several other ways of creating templates, but they just don't match the criteria.
here is the example for both:
AddItem.js - using render 😠 functions
'use strict';
Vue.component('add-item', {
methods: {
add() {
this.$emit('add', this.value);
this.value = ''
}
},
data () {
return {
value: ''
}
},
render(createElement) {
var self = this
return createElement('div', [
createElement('input', {
attrs: {
type: 'text',
placeholder: 'new Item'
},
// v-model functionality has to be implemented manually
domProps: {
value: self.value
},
on: {
input: function (event) {
self.value = event.target.value
// self.$emit('input', event.target.value)
}
}
}),
createElement('input', {
attrs: {
type: 'submit',
value: 'add'
},
on: {
click: this.add
}
}),
])
}
});
ListItem.js - using template literals (back-ticks)
'use strict';
Vue.component('list-item', {
template: `<div class="checkbox-wrapper" #click="check">
<h1>{{checked ? '☑' : '☐'}} {{ title }}</h1>
</div>`,
props: [
'title',
'checked'
],
methods: {
check() {
this.$emit('change', !this.checked);
}
}
});
and the html
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.0/vue.js"></script>
<script src="ListItem.js"></script>
<script src="AddItem.js"></script>
</head>
<body>
<div id="app">
<add-item #add='list.push({title:arguments[0], checked: false})'></add-item>
<list-item v-for="(l, i) in list" :key="i" :title="l.title" :checked="l.checked" #change="l.checked=arguments[0]"></list-item>
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
newTitle: '',
list: [
{ title: 'A', checked: true },
{ title: 'B', checked: true },
{ title: 'C', checked: true }
]
}
});
</script>
</body>
</html>
TL; DR;
See it in action at : https://repl.it/OEMt/9
You cant. You must use async components - read guide here
Actually you can. This is kinda easy. Depends on your needs and situation. However, this code is NOT technically correct, however it will explain to you how it might work, gives you massive freedom and makes your original vue instance smaller.
To make this work, you will need vue router (cdn is ok) and in this case axios or fetch (if you dont care about supporting older browsers).
The only downfall in my opinion is that in content files you will need to add additional call parameter $parent . This will force vue to work.
index
<div id="app">
<router-link v-for="route in this.$router.options.routes" :to="route.path" :key="route.path">{{ route.name }}</router-link>
<section style="margin-top:50px;">
<component :is="magician && { template: magician }" />
</section>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
const viewer = axios.create({ baseURL: location.origin });
const routes = [
{"name":"Hello","slug":"hello","path":"/lol/index.html"},
{"name":"Page One","slug":"page_one","path":"/lol/page-one.html"},
{"name":"Page Two","slug":"page_two","path":"/lol/page-two.html"}
];
const app = new Vue({
router,
el: '#app',
data: {
magician: null,
},
watch: {
$route (to) {
this.loader(to.path);
}
},
mounted() {
this.loader(this.$router.currentRoute.path);
},
methods: {
viewer(opt) {
return viewer.get(opt);
},
loader(to) {
to == '/lol/index.html' ? to = '/lol/hello.html' : to = to;
this.viewer(to).then((response) => {
this.magician = response.data;
}).catch(error => {
alert(error.response.data.message);
})
},
huehue(i) {
alert(i);
}
}
});
</script>
hello.html content
<button v-on:click="$parent.huehue('this is great')">Button</button>
page-one.html content
<select>
<option v-for="num in 20">{{ num }}</option>
</select>
page-two.html content
// what ever you like
router explanation
To make this work perfectly, you will need to find a correct way to configure your htaccess to render everything if current page after first view is not index. Everything else should work fine.
As you can see, if it is index, it will load hello content file.
I faced the same issue and this is how I solved it , I also made a video about this question https://www.youtube.com/watch?v=J037aiMGGAw
create a js file ,for your component (logic) let's call it "aaaa.vue.js"
create an HTML file for your template that will be injected in your "aaaa.vue.js" and let's call it "aaaa.html"
Component file (Logic file javascript)
const aaaa = {
name:"aaaa",
template: ``,
data() {
return {
foo:"aaaa"
};
},
methods: {
async test() {
alert(this.foo)
},
},
};
Template file (HTML)
<!--template file-->
<div>
<button #click="test" > click me plz </button>
</div>
index.html
<html>
<head>
<title>my app</title>
</head>
<body>
<div id="app" class="main-content col-12">
<aaaa></aaaa>
</div>
</body>
</html>
<script src="axios.min.js"></script>
<script src="vue.js"></script>
<!-- load js file (logic) -->
<script src="aaaa.vue.js"></script>
<script>
document.addEventListener("DOMContentLoaded", async function () {
//register components
let html = await axios.get("aaaa.html"); // <---- Load HTML file
aaaa.template = html.data;
Vue.component("aaaa", aaaa);
new Vue({
el: "#app",
name: "main",
//... etc
});
});
</script>
Update :
I also created an example on github to see it in action
https://github.com/nsssim/Vue-CDN-load-component
Sure you can, this is the way we are doing it in all our components of our app.
<template src="../templates/the_template.html"></template>
<script>
export default {
name: 'ComponentName',
props: {},
computed: {},
methods: {},
};
</script>
<style lang="scss">
#import '../styles/myscss_file';
</style>
Will need to add
runtimeCompiler: true
to your vue.config.js file. That's it.
Everything is fine in my main.js
import User from './components/User.vue'
new Vue({
el: '#user',
render: h => h(User),
data() {
return {
groups: []
}
},
mounted() {
this.getGroups();
},
methods: {
getGroups: function () {
axios.get('http://vagrant.dev/groups')
.then(response => this.groups = response.data)
.catch(error => console.log(error));
}
}
});
User.vue
<template>
<div id="user">
{{groups}} <!-- must be printed but it doesn't seem -->
</div>
</template>
<script>
export default {
name: 'user',
props: ['groups']
}
</script>
and index.html
<div id="user">
<user :groups="groups"></user>
</div>
Where is the mistake?
I do not get any errors, but I didn't understand why the value was not printed on the screen
Seems like you are putting 2 Vue instances on the same template since in your main file you are defining the template as el: "#user" which is already controlled by User.vue.
In you index.html add a div with id="app" and in main.js set el: "#app"
Your main.js and index.html shouldn't mix template in HTML and render function. So your main.js should be:
```new Vue({
el: '#user',
components: { User },
data() {
return {
groups: []
}
},
...```
You shouldn't directly reassign data value because Vue cannot detect property additions and rerender view. You should do it via Vue.set or this.$set like this:
this.$set(this, 'groups', response.data)
You can read more about how vue reactive in https://v2.vuejs.org/v2/guide/reactivity.html and Vue.set API: https://v2.vuejs.org/v2/api/#Vue-set
I'm new to vuejs and just started playing with it. While trying different tutorials I'm stuck at this code sample which is not working. Can anyone please explain why the second-component is not being rendered?
Vue.component('first-component', {
template: `<div>This is first component: {{val}}!</div>`,
data: function () {
return {
val: "FIRST <second-component></second-component>"
}
},
})
Vue.component('second-component', {
template: `<p>This is second component: {{val}}</p>`,
data: function () {
return {
val: 'SECOND'
}
},
})
new Vue({
el: '#example'
})
<script src="https://unpkg.com/vue#2.1.10/dist/vue.js"></script>
<div id="example">
<first-component></first-component>
</div>
The problem is you have put the <second-component> in the val variable, and trying to render it with Mustache syntax However as stated in docs The double mustaches interprets the data as plain text, not HTML
You can use v-html to insert the component as plain HTML but again it is stated: the contents are inserted as plain HTML - they will not be compiled as Vue templates.
The only way you can render second-component is by putting this in the template:
template: `<div>This is first component: {{val}}!<second-component></second-component></div>`,
That's because you are returning it as "data" in "val". So that's not evaluated to a component. If you put it in the template, it works.
Vue.component('first-component', {
template: `<div>This is first component: {{val}}! <second-component></second-component></div>`,
data: function () {
return {
val: "FIRST"
}
},
})
Vue.component('second-component', {
template: `<p>This is second component: {{val}}</p>`,
data: function () {
return {
val: 'SECOND'
}
},
})
new Vue({
el: '#example'
})
<script src="https://unpkg.com/vue#2.1.10/dist/vue.js"></script>
<div id="example">
<first-component></first-component>
</div>