Vuejs Reactive propery interpolation is not working - vue.js

I've run into an issue where i'm creating components that are then being applied to the root App - after creating a dynamic child w/ vanilla JS. When i look at the Vue object in the console, message is not present, which i expect it to be - Can anyone tell me why?
Create the App
Dynamically add new DOM element w/ createElement with a {{ message }} property (ex: <div id="test">{{message}}</div>)
Create a custom component using Vue.Component (ex: <custom-component><custom-component> w/ pre-populated {{ messsage }} value test message
Render the Vue w/ the component w/ update props values for {{ message }}
Below is the actual code tested:
import Vue from 'vue/dist/vue.js';
export default {
name: 'app',
components:
{
HelloWorld
},
data()
{
return this;
},
mounted()
{
// #2 Create an Html Target that contains the component's name 'custom-element'
var v = document.createElement('div');
v.setAttribute('id', 'test');
v.innerHTML = '<custom-element></custom-element>';
var $element = this.$el.prepend(v);
// #1 Create a component
var MyComponent = Vue.component(
'custom-element',
{
template: '<div v-bind:id="UID">{{message}}</div>',
prop: ['UUID', 'message'],
data() {
return {
UID: '',
message: 'test message',
}
},
}
);
// #3 Append the component to the Html Target
window.vm = new Vue({
el: '#test',
components: {
'custom-component': MyComponent,
},
beforeCreate() {
return {
UID: 'x7x7x',
message: 'test message update...'
}
},
})
window.console.log(MyComponent);
window.console.log(this);
}
}`
Here's the main index.html:
`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>hello-world</title>
</head>
<body>
<noscript>
<strong>We're sorry but hello-world doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>'
Here's the main.js
'use strict'
import Vue from 'vue'
import App from './App.vue'
import Reaktr from './js/reaktr.js'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
data: {
Reaktr: new Reaktr(),
},
mounted() {
}
}).$mount('#app')
Here's the Helloworld.vue
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>

Related

How can I use passed data using props in child component v-bind:style?

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>

Vue component working main Vue instance but not in Vue Router component

I have set up a Laravel / Vue app with the main element (#app) for my app in my welcome.blade.php file.
Then I have app.js file in which I initiate my Vue instance. And then there's my routes.js and MyComponent.vue files.
In MyComponnent.vue I am trying to load vue-winwheel. But I keep getting this warning:
[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.
And the component won't load. If I use directly in my welcome.blade.php file it does load, but in the wrong place of course.
I did register VueWinwheel globally (tested both VueWinwheel and vue-winwheel).
Anyone have any ideas what I'm missing?
app.js
import Vue from 'vue';
import Vuex from 'vuex'
import VueRouter from 'vue-router';
import BootstrapVue from 'bootstrap-vue'
import VueWinwheel from 'vue-winwheel/vue-winwheel'
import routes from './routes';
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
Vue.use(Vuex);
Vue.use(VueRouter);
Vue.use(BootstrapVue);
Vue.use(VueWinwheel);
require('./bootstrap');
let app = new Vue({
el: '#app',
router: new VueRouter(routes),
components: {
VueWinwheel
}
});
welcome.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="icon" type="image/png" href="{{ asset('images/FavIcon-64.png') }}" />
<link rel="stylesheet" href="{{ mix('/css/app.css') }}">
<title>My App with VueWinwheel</title>
</head>
<body>
<div id="app" class="col-xs-12 text-center">
<transition name="slideFade" mode="out-in">
<router-view></router-view>
</transition>
<vue-winwheel /> <!-- This one does work -->
</div>
<script src="/js/app.js"></script>
</body>
</html>
MyComponent.vue
<template>
<section class="winwheel-section">
<vue-winwheel /> <!-- This one does not work and makes the warning show in console -->
</section>
</template>
<script>
module.exports = {
data: function(){
return {
}
}
}
</script>
router.js
import MyComponent from './components/MyComponent';
export default{
mode: 'history',
routes: [
{
path: '/',
component: MyComponent,
name: 'MyComponent'
}
]
}
UPDATE
I have tried what #AbdulAzeez Olanrewaju suggested (and tried it before). But this gave me an error in my npm vue watch terminal:
"export 'default' (imported as 'mod') was not found in '-!../../../node_modules/babel-loader/lib/index.js??ref--4-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Spin.vue?vue&type=script&lang=js&'
You could try and change
let app = new Vue({
el: '#app',
router: new VueRouter(routes),
components: {
VueWinwheel
}
});
to
let app = new Vue({
el: '#app',
router: new VueRouter(routes),
components: {
'vue-winwheel': VueWinwheel
}
});
Also i do not think you need to use the Vue.use(VueWinWheel);
I have found the answer.
I could not import Winwheel inside my MyComponent.vue because I used module.exports.
When I use export default it did work.
So:
<!-- This -->
<script>
export default {
data: function(){
return {
}
}
}
</script>
<!-- Instead of this -->
<script>
module.exports = {
data: function(){
return {
}
}
}
</script>
<!-- Note that I also remove the = after module.exports

Vue - Import components in a multi-page environment

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>

Vuejs single file components mixed with normal components

I am trying to mix vuejs single file components with the normal style of components (not sure what they are called) which I have existing code developed for already.
main.js
import Vue from 'vue'
import test from './test.vue'
import VueMaterial from 'vue-material'
Vue.use(VueMaterial)
new Vue({
el: '#app',
render: h => h(test,
{props: {
testprop: 'ttttt'
}
}),
data:{
// /testprop: 'tytytytyty'
}
})
test.vue
<template>
<div>
<my-component></my-component>
<div>This is the first single page component</div>
</div>
</template>
<script>
import MyComponent from '../src/components/MyComponent.js'
import TestTest from '../src/components/TestTest.vue'
export default {
name: 'MainApp',
props: ['testprop'],
components: {
TestTest,
MyComponent
},
mounted: function(){
},
computed:{
returnProp: function(){
return this.testprop
}
}
}
</script>
<style lang="scss" scoped>
.md-menu {
margin: 24px;
}
</style>
MyComponent.js Normal style component
window.Vue = require('Vue') //would give errors vue undefined if i dont't add this line
Vue.component('my-component', {
name: 'my-component',
template: '<div>Normal component</div>'
})
index.html
<html lang="en">
<head>
<meta charset="utf-8">
<meta content="width=device-width,initial-scale=1,minimal-ui" name="viewport">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic|Material+Icons">
<link rel="stylesheet" href="https://unpkg.com/vue-material#beta/dist/vue-material.min.css">
<link rel="stylesheet" href="https://unpkg.com/vue-material#beta/dist/theme/default.css">
<title>vuematerial</title>
</head>
<body>
<div id="app">
<main-app :testprop="testprop"></main-app>
</div>
<script src="dist/build.js"></script>
</body>
</html>
The single file component and a child single file component (not showed here) display fine. The normal type will show up as
<!--function (t,n,r,i){return Mt(e,t,n,r,i,!0)}-->
In the generated html.
Iv'e also tried doing the MyComponent import in the main.js file.
Any ideas?
I don't really want to convert all my existing components into single file ones :(
According to the docs, a child component is an object, not something attached to the Vue instance (i.e Vue.component()) so declare your component like this:
MyComponent.js
export default {
name: 'my-component',
template: '<div>Normal component</div>'
}
If you want to keep the format of MyComponent as is then you'll need to register the component before the new Vue call.

how do i show content in this vue example?

I'm playing with vue for the first time and have knocked up a simple test file. I have a table that is populated by data from an api call, and have used the vue router to create links to each item but this link isn't displaying the content. the network shows it's making the request to the api, but for some reason the template is not showing (not even the hard-coded content). Why? Also, why does the route content not display on the first router view, but only the router-view in the tbl component?
<!doctype html>
<html lang="en">
<head>
<title>Vue.js test</title>
<meta charset="utf-8">
</head>
<body>
<div id="app">
<!-- this route displays correctly -->
<router-link to="/foo">Go to Foo</router-link>
<table-notification/>
<!-- content is not displayed here - why? -->
<router-view></router-view>
</div>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vue-router"></script>
<script src="axios.min.js"></script>
<script>
const foo = {template:'<div>asdfasdf</div>',};
var router = new VueRouter({
routes: [
{path: '/foo', component: foo},
{path: '/notifications/:id', component: notification_view}
]
});
var app = new Vue({
router: router
}).$mount('#app');
var notification_view = new Vue({
router: router,
template: `
<div>iop
id: {{ obj.id}}<br/>
title: {{ obj.data.title}}<br/>
message: {{obj.data.message}}<br/>
</div>
`,
data: {
obj: {},
id: 0,
},
watch: {
'$route' (to, from) {
// check for id in url
if (this.$route.params.id)
this.update_notification();
}
},
methods: {
update_notification: function(){
this.id = this.$route.params.id;
axios.get('http://api2/notifications/' + this.id)
.then(response => {this.obj = response.data.packet;});
}
}
});
var tbl = new Vue({
router:router,
el: 'table-notification',
template: `
<div>
<table>
<tr>
<th>Title</th>
<th>Created</th>
<th>Actions</th>
</tr>
<tr v-for="obj in objects">
<td><router-link :to="link(obj)">{{obj.data.title}}</router-link></td>
<td>{{obj.created}}</td>
<td>actions</td>
</tr>
</table>
<router-view/>
<!-- why must router-view be here, and why isn't notification_view showing any output?-->
</div>
`,
methods: {
link: function(obj) {return '/notifications/' + obj.id;}
},
data: {
objects: [],
},
created: function(){
axios.get('http://api2/notifications').
then(response =>
{
this.objects = response.data.packet;
});
}
});
</script>
</body>
</html>
I think you are misunderstanding the idea of Vue instances...
In you example you have:
a JSON foo that I think it is a component,
An App instance, which is mounted to the #app element
Another instance called notification_view with the same router, what I think is is another component
Another tbl instance, that I think it is another component
You actually need one instance and a bunch of components as in this example:
https://jsfiddle.net/dcr3jyzo/