Vue - Import components in a multi-page environment - vue.js

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>

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>

How do I create and instantiate a store using VueX called via cdn?

I'm working on a project that's php/vuejs. There's no npm nor yarn nor any tool to install packages so the team members always add the cdn link to everything they need. In this case I need to add Vuex + vuex-persistedstate but I don't get to see how to initiate it and instantiate it... litterally no idea. If somebody could show me where I can find this information or post it here as an answer I will be more than thankful.
I tried this and it didn't work:
vueInstance.js
const app = new Vue({
el: '#app',
store: store,
...
footer.php
<script src="https://unpkg.com/vuex"></script>
<script src="https://unpkg.com/vuex-persistedstate/dist/vuex-persistedstate.umd.js"></script>
<script> Vue.use(Vuex)</script>
store.js
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
i made an example how use cdn and vuex + vuex-persist (a simple counter app)
when you change the count you can see your browser localStorage for see changes
and i hope this help you :)
important note:
only use vuex-persist v2.2.0 the latest version (v3.1.3) have problem and show error message in browser.
you can see it also in codepen: https://codepen.io/Mohamadmasoudi/pen/KKaZMOo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vuex - VuexPersist example</title>
</head>
<body>
<div id="app">
count is: {{count}}
<button #click="increment">+</button>
<button #click="decrement">-</button>
</div>
<script src="https://vuejs.org/js/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuex-persist#2.2.0"></script>
<script src="https://unpkg.com/vuex#3.6.2/dist/vuex.js"></script>
<script>
const vuexLocal = new window.VuexPersistence.VuexPersistence({
storage: window.localStorage,
});
const store = new Vuex.Store({
state: { count: 0 },
mutations: {
increment (state) {
state.count++
},
decrement (state) {
state.count--
}
},
actions: { },
plugins: [vuexLocal.plugin]
});
vm = new Vue({
el: "#app",
store: store,
methods: {
increment(){
store.commit('increment');
},
decrement(){
store.commit('decrement');
}
},
computed: {
count(){
return store.state.count
}
}
});
</script>
</body>
</html>

Vuejs Reactive propery interpolation is not working

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>

Possible to use VueJS SFC components with template in rendered html?

I have experience with both single page apps and multi-page apps (classic websites). In the past I have used AngularJS 1.x on each page, it has been useful because all components can live in separate files and be executed as they appear on each page.
I'm now looking at VueJS to replace AngularJS, but not finding it easy to understand how to architect my multi-page app.
As expected I want to use some components on all the pages, and some on only a few pages.
Example:
I came across SFC - single file components using ES2015 which looked promising, but my backend is Java which outputs my html from JSPs. It appears that .vue files are precompiled by webpack, but if my templates are only ready when the page is rendered that won't be possible will it?
How would one architect a solution so that each component is modular but utilize either an x-template in the html and somehow attach it to a .vue SFC, or is there some other way to have components in separate files which can be imported using ES2015?
I hope this is making sense, can't seem to figure it out.
One possible approach would be to set the template for the Vue Component inline. So this would be to have a Component File like
Home.vue:
<script>
export default {
data() {
return {
msg: 'text',
}
}
}
</script>
import it as a global component for Vue (using require, import, etc.)
Vue.component('home', require('./components/Home.vue'));
and in your server generated HTML you'd have to use an inline template, which will have all the flexibility from normal templates
home.jsp:
<home inline-template>
<h2 v-text="msg"></h2>
</home>
Update
I've added an example on GitHub here
If I understand your question, you have want to make single file components out of HTML.
If this is the case, you should make use of the render() function and regular components.
The render function decides what to use as a template for a component:
<!DOCTYPE html>
<html>
<head>
<title>Vue</title>
</head>
<body>
<div id="app">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
render (createElement) {
return createElement({
template: '<div>Hello World</div>'
})
},
})
</script>
</body>
</html>
will render Hello World to the screen.
Now, let's see how this function is reactive:
<script type="text/javascript">
new Vue({
el: '#app',
data: {
count: 0
},
render (createElement) {
return createElement({
template: '<div>Hello World ' + this.count + '</div>'
})
},
created () {
setTimeout(() => {
this.count++
}, 2000)
}
})
</script>
Here, after 2 seconds, the counter in <div>Hello World ' + this.count + '</div> will increment from 0 to 1.
Now, what if we want to separate the template from the data?
<script type="text/javascript">
new Vue({
el: '#app',
render (createElement) {
return createElement({
template: '<div>Hello World {{ count }}</div>',
data () {
return {foo: 'bar'}
}
})
}
})
</script>
This code will display Hello World bar.
Now, let's see what happen if we try to load our template over http. We'll use the axios library to do so. Let's create a remote.html file to contain our html code:
<div>
I'm a remote component {{ foo }}
</div>
Now, let's try to load it via Ajax:
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.16.2/axios.min.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
template: null
},
render (createElement) {
return createElement({
template: this.template ? this.template : '<div>Hello World {{ foo }}</div>',
data () {
return {foo: 'bar'}
}
})
},
created () {
axios({
url: '/remote.html',
method: 'get'
}).then(response => {
this.template = response.data
})
}
})
</script>
This code will display I'm a remote component {{ foo }} as soon as remote.html has been loaded from the browser.
Note that the object passed to the createElement function is actually a component structure. You can use the same methods on it:
render (createElement) {
return createElement({
template: this.template ? this.template : '<div>Hello World {{ foo }}</div>',
data () {
return {foo: 'bar'}
},
mounted () {
alert('Hello from mounted')
}
})
}
will trigger an alert on the browser.
Anyway, here is a complete example with nested components:
Index.html
<!DOCTYPE html>
<html>
<head>
<title>Vue</title>
</head>
<body>
<div id="app">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.16.2/axios.min.js"></script>
<script type="text/javascript">
const headerComponent = {
data () {
return {
template: '<div>Loading...</div>'
}
},
render (createElement) {
return createElement({
template: this.template,
data () {
return {
search: ''
}
}
})
},
created () {
axios('/header.html').then(response => {
this.template = response.data
})
}
}
new Vue({
el: '#app',
data: {
template: null
},
render (createElement) {
return createElement({
template: this.template ? this.template : 'Loading...',
data () {
return {foo: 'bar'}
},
components: {
'my-header': headerComponent
}
})
},
created () {
axios({
url: '/remote.html',
method: 'get'
}).then(response => {
this.template = response.data
})
}
})
</script>
</body>
</html>
header.html
<div>
<label>Search</label>
<input v-model="search" name=""> The search is: {{ search }}
</div>
I'm not sure that this is really the best approach and if I'm really responding to the question, but it will at list give you some tips on how Vue handles rendering and components...

Vue.js component issue

js i'm starting to catch up on it but i'm stuck on components would appreciate your help thanks
//here is my js
Vue.component('thatsCool', {
template: document.querySelector('#myOwnTemplate'),
data: function() {
return {
helloWorld: 'thats cool',
};
},
});
new Vue({
el: 'body',
});
//and this is my html
<! DOCTYPE html>
<html>
<head>
<title>playing with Vue components</title>
</head>
<body>
<thatsCool></thatsCool>
<script id="myOwnTemplate" type="x/template">
<p v-text="helloWorld"></p>
</script>
<script src="vue.js"></script>
<script src="component.js"></script>
</body>
</html>
There are a couple of errors in your code. Use dash-separated convention for your components and simple handlebar notation for string output. Try with this code:
HTML
<thats-cool></thats-cool>
<script id="myOwnTemplate" type="x-template">
<p>{{ helloWorld }}</p>
</script>
JS
Vue.component('thats-cool', {
template: '#myOwnTemplate',
replace : true,
data: function() {
return {
helloWorld: 'thats cool',
};
}
});
Note that the option 'replace : true' replaces the original template's content of el instead of appending to it.