I'm having trouble running components using Vue. I don't know if I'm using the correct CDN links, but it seems like it's not working at all.
Template
<div id="app">
<button v-on:click="showing = !showing">show or hide</button>
<transition name="slide-fade" tag="div">
<div v-if="showing">Hello!</div>
</transition>
<weather-meter></weather-meter>
</div>
<script type="text/x-template" id="weather-meter-template">
<div>
Today's high: {{high}}
<div class="pointer" v-bind:style:="{width: showHigh}"></div>
How we feel about this: {{ourFeelings}}
</div>
</script>
Javascript
new Vue({
el:'app',
data: function(){
return{
showing: true
}
}
});
Vue.component("weather-meter", {
template:"#weather-meter-template",
data:function (){
return{
high:40,
shownHigh: 40,
ourFeelings: "meh"
}
These are the CDN scripts I'm using as well.
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.4/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.1/TweenMax.min.js"></script>
Related
I have something I have been trying to do which is challenging. I have a simple div that gets appended to the top level on the click of a button. The issue is I want vuejs data appended inside of this div. I am not quite sure how to bind this data, I have tried using a simple expression, but no luck. Can someone please let me know how this can be solved--and with a div, not a bootstrap modal
new Vue({
el: "#app",
data: {
chocs:[{"title":'a man tale'},{"title":'a boy tale'}]
},
methods: {
handleTileClick: function(){
alert(this.chocs[0].title);
$("#fox").append(`<div id="popover-dialog"> data here {{this.chocs[0].title}}
</div>`);
},
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div id="app">
<h2>Todos:</h2>
<button v-on:click="handleTileClick()">
Click Me
</button>
<div id="fox">
</div>
</div>
Without JQuery, the Vue-way:
new Vue({
el: "#app",
data: () => ({
chocs:[{"title":'a man tale'}, {"title":'a boy tale'}],
titleToBeAppended: ''
}),
methods: {
handleTileClick: function(){
this.titleToBeAppended = this.chocs[0].title
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div id="popover-dialog">
<p>Data here: {{ titleToBeAppended }}</p>
<button v-on:click="handleTileClick()">Click Me</button>
</div>
</div>
Using template literals:
new Vue({
el: "#app",
data: () => ({
chocs:[{"title":'a man tale'}, {"title":'a boy tale'}]
}),
methods: {
handleTileClick: function(){
alert(this.chocs[0].title);
$("#fox").append(
`<div id="popover-dialog">data here: ${this.chocs[0].title}</div>`
);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div id="app">
<h2>Todos:</h2>
<button v-on:click="handleTileClick()">Click Me</button>
<div id="fox"></div>
</div>
I have created a file EmptyComponent.html to show a Vue.js component (myComponent.vue) both files are in the same folder. my component will not show and I am always getting an error in chrome developer tools console saying "Uncaught SyntaxError: Unexpected identifier EmptyComponent.html:8"
EmptyComponent.html
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>
<div id="app">
<h1> id app div </h1>
<myComponent></myComponent>
</div>
<script>
import myComponent from 'myComponent.vue'
new Vue({
el: '#app',
components: {myComponent}
});
</script>
myComponent.vue
<template>
<div>
<h1> myComponent div</h1>
</div>
</template>
<script>
export default {
name: 'myComponent'
</script>
<style scoped>
</style>
In order to use single file components .vue you should use Vue cli 3, but your component does not contain a complex code you could use CDN and declare your component using Vue.component('my-component',{....}) :
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>
<div id="app">
<h1> id app div </h1>
<my-component></my-component>
</div>
<script>
Vue.component('my-component', {
template: ` <div>
<h1> myComponent div</h1>
</div>`
})
new Vue({
el: '#app',
});
</script>
Does vue.js have an equivalent of Angular's *ngTemplateOutlet directive? Let's say I have some components defined like this:
<template>
<div id="independentComponent">
Hello, {{firstName}}!
</div>
</template>
<script>
export default {
name: "independentComponent",
props: ['firstName']
}
</script>
...
<template>
<div id="someChildComponent">
<slot></slot>
<span>Let's get started.</span>
</div>
</template>
<script>
export default {
name: "someChildComponent"
}
</script>
I want to be able to do something like this:
<template>
<div id="parentComponent">
<template #indepdentInstance>
<independentComponent :firstName="firstName" />
</template>
<someChildComponent>
<template #indepdentInstance></template>
</someChildComponent>
</div>
</template>
<script>
export default {
name: "parentComponent",
components: {
someChildComponent,
independentComponent
},
data() {
return {
firstName: "Bob"
}
}
}
</script>
In Angular, I could accomplish this with
<div id="parentComponent">
<someChildComponent>
<ng-container *ngTemplateOutlet="independentInstance"></ng-container>
</someChildComponent>
<ng-template #independentInstance>
<independentComponent [firstName]="firstName"></independentComponent>
</ng-template>
</div>
But it looks like Vue requires the element to be written to the DOM exactly where it is in the template. Is there any way to reference an element inline and use that to pass to another component as a slot?
You cannot reuse templates like ngTemplateOutlet, but can combine idea of $refs, v-pre and runtime template compiling with v-runtime-template to achieve this.
First, create reusable template (<ng-template #independentInstance>):
<div ref="independentInstance" v-show="false">
<template v-pre> <!-- v-pre disable compiling content of template -->
<div> <!-- We need this div, because only one root element allowed in templates -->
<h2>Reusable template</h2>
<input type="text" v-model="testContext.readWriteVar">
<input type="text" v-model="readOnlyVar">
<progress-bar></progress-bar>
</div>
</template>
</div>
Now, you can reuse independentInstance template:
<v-runtime-template
:template="$refs.independentInstance.innerHTML"
v-if="$refs.independentInstance">
</v-runtime-template>
But keep in mind that you cannot modify readOnlyVar from inside independentInstancetemplate - vue will warn you with:
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "readOnlyVar"
But you can wrap it in object and it will work:
#Component({
components: {
VRuntimeTemplate
}
})
export default class ObjectList extends Vue {
reusableContext = {
readWriteVar: '...'
};
readOnlyVar = '...';
}
You could try Portal vue written by LinusBorg a core Vue team member.
PortalVue is a set of two components that allow you to render a
component's template (or a part of it) anywhere in the document - even
outside the part controlled by your Vue App!
Sample code:
<template>
<div id="parentComponent">
<portal to="independentInstance">
<!-- This slot content will be rendered wherever the <portal-target>
with name 'independentInstance' is located. -->
<independent-component :first-name="firstName" />
</portal>
<some-child-component>
<portal-target name="independentInstance">
<!--
This component can be located anywhere in your App.
The slot content of the above portal component will be rendered here.
-->
</portal-target>
</some-child-component>
</div>
</template>
There is also a vue-simple-portal written by the same author that is smaller but that mounts the component to end of body element.
My answer from #NekitoSP gave me an idea for a solution. I have implemented the sample below. It worked for me. Perhaps you want to use it as a custom component with props.
keywords: #named #template #vue
<template>
<div class="container">
<div ref="templateRef" v-if="false">write here your template content and add v-if for hide in current place</div>
....some other contents goes here
<p v-html="getTemplate('templateRef')"></p>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
Vue.extend({
methods:{
getTemplate(tempRef){
return this.$refs[tempRef].innerHTML
}
}
})
</script>
X-Templates
Use an x-template. Define a script tag inside the index.html file.
The x-template then can be referenced in multiple components within the template definition as #my-template.
Run the snippet for an example.
See the Vue.js doc more information about x-templates.
Vue.component('my-firstname', {
template: '#my-template',
data() {
return {
label: 'First name'
}
}
});
Vue.component('my-lastname', {
template: '#my-template',
data() {
return {
label: 'Last name'
}
}
});
new Vue({
el: '#app'
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<my-firstname></my-firstname>
<my-lastname></my-lastname>
</div>
<script type="text/x-template" id="my-template">
<div>
<label>{{ label }}</label>
<input />
</div>
</script>
Not really sure i understand your problem here, but i'll try to give you something that i will opt to do if i want to add two components in one template.
HeaderSection.vue
<template>
<div id="header_id" :style="'background:'+my_color">
welcome to my blog
</div>
</template>
<script>
export default {
props: ['my_color']
}
</script>
BodySection.vue
<template>
<div id="body_id">
body section here
</div>
</template>
<script>
export default {
}
</script>
home.vue
<template>
<div id="parentComponent">
<header-section :color="my_color" />
<body-section />
</div>
</template>
<script>
import HeaderSection from "./components/HeaderSection.vue"
import BodySection from "./components/BodySection.vue"
export default {
name: "home",
components: {
HeaderSection,
BodySection
},
data() {
return {
my_color: "red"
}
}
}
</script>
I registered component in my app.js like this:
Vue.component('navbar', require('./components/Navbar.vue'));
Now I want to import that component:
<template>
<nav class="navbar">CODE HERE</nav>
</template>
Into my blade.php file:
<body class="">
<div id="app">
<div class="">
<navbar></navbar> <-- here!
#yield('content')
</div>
</div>
</body>
What's the easiest way to do this?
In app.js
import navbar from './components/Navbar.vue';
Vue.component('navbar', require('./components/Navbar.vue'));
var app = new Vue({
el: '#app',
components: {
'navbar': require('./components/Navbar.vue'),
}
});
In your blade:
<body class="">
<div id="app">
<div class="">
<navbar></navbar>
#yield('content')
</div>
</div>
It's an old thread, but: don't forget to run npm run dev to compile the app.js
I'm trying to use flow-router to render templates within a template based on nested routes. Rereading that confused me so I'll give an example.
Main Container:
<body>
<header>
<div id="headerRight">
<span class="headerButton" id="teachButton">Teach</span>
</div>
</header>
<div class="container" style="padding: 50px;">
{{> mainLayout}}
</div>
</body>
<template name="mainLayout">
<main>
{{>Template.dynamic template=main}}
</main>
</template>
Main Container JS:
FlowRouter.route('/', {
action: function() {
BlazeLayout.render("mainLayout", {main: "base"});
}
});
FlowRouter.route('/createCourse', {
action: function() {
BlazeLayout.render("mainLayout", {main: "courseChooseCont"});
}
});
Nested Routes:
<template name="courseChooseCont">
<header>
<i class="fa fa-times" aria-hidden="true"></i>
</header>
<ul>
<li>Category</li>
<li>Availability</li>
<li>Simple Availability</li>
</ul>
{{> courseLayout}}
<div name="courseMain"></div>
<div class="bottomBar">
<div class="back">Back</div>
<div class="next">Next</div>
</div>
</template>
<template name="courseLayout">
<main>
{{>Template.dynamic template=content}}
</main>
</template>
Nested Routes JS:
var createCourse = FlowRouter.group({
prefix: '/createCourse'
});
createCourse.route('/', {
action: function() {
BlazeLayout.render("courseLayout", {content: "base"});
}
});
createCourse.route('/availabilityCheck', {
action: function() {
BlazeLayout.render("courseLayout", {content: "availabilityCheck"});
}
});
createCourse.route('/simpleAvailability', {
action: function() {
BlazeLayout.render("courseLayout", {content: "simpleAvailability"});
}
});
When I render the nested routes it seems to overwrite the "courseChooseCont" template that should be housing the nested template and is simply displaying the nested template inside the 'Main Container'.
I'm assuming I'm using BlazeLayout wrong but I can't seem to find a solution.