Create a custom component in Vue.js - javascript

I'm currently learning JavaScript, HTML, and Vue.Js, and now how to work with components.
I'm taking an online course which corrects code using a bot.
The assignment is to create a component, greet that produces <div>hello!</div>when it's called using <greet></greet>. To complete the assignment I need to use Vue.Component and the templete-key.
I need to set the el-value at new Vue-caller so it matches <div id="app"></div>
This is in my HTML code so far(with script src included):
<body>
<div id="app">
<greet="greet"></greet>
</div>
</body>
This is my my Vue code so far
new Vue({ el: '#app' })
Vue.component('greet', {
data() {
return {
greet
}
},
template: '<div>hello!</div>'
})
The output on the HTML page is just blank, so I don't understand what I'm missing here.
The output from the bot is:
file.js
✓ exists
✓ is valid JavaScript
1) renders the correct markup

When you use the syntax Vue.component() you are registering a component globally, so it can be used by any new Vue instances created afterward. So:
new Vue({ el: '#app' }) // this Vue instance does not contain the greet component because it does not exists yet.
Vue.component('greet', {
data() {
return {
}
},
template: '<div>hello!</div>'
})
Instead:
Vue.component('greet', {
data() {
return {
}
},
template: '<div>hello!</div>'
})
new Vue({ el: '#app' }) // this Vue instance will contain the greet component because it was already created and registered.
Also <greet="greet"></greet> is not valid syntax. It should be <greet></greet>.
You should remove greet from data() function. it has no meaning and use.
The final code should look like:
<body>
<div id="app">
<greet></greet>
</div>
</body>
Vue.component('greet', {
template: '<div>hello!</div>'
})
new Vue({ el: '#app' })

There are couple of mistakes here.
First <greet="greet"></greet> doesn't work. There's something calles props in vue (you'll learn it in future) Change that line to <greet></greet>
Then you don't have to use data() to show hello div. Delete the greet from data.
Above steps might fix your fault

Related

Vue.js component: Props as object doesn’t work with x-template

To simplify the markup of a Vue component, I’m trying to use an object for the props.
When defining the template of the component as described in the code example on Components Basics — Vue.js all works fine. But trying to define the template as an x-template, I’m getting an error saying, that the property 'title' of undefined cannot be read.
Here’s the code:
<div id="app">
<script type="text/x-template" id="post-template">
<div class="blog-post">
<h3>{{ post.title }}</h3>
<div v-html="post.content"></div>
</div>
</script>
<blog-post v-for="post in posts" v-bind:key="post.id" v-bind:post="post"></blog-post>
</div>
const data = {
posts: [
{
title: "Hello World",
content: "Bar"
}
]
};
let postComponent = {
props: ['post'],
template: 'post-template'
}
const vue = new Vue({
el: '#app',
components: {
'blog-post': postComponent
},
data() {
return data;
}
});
Is it not possible to access object properties in a x-template or is there something wrong with my code?
Two things:
Take the x-template outside of your app div. Vue is going to replace all the content in the div, so that template will be lost
postComponent should refer to template with a selector, so #post-template instead of post-template
Here's a demo of it working: https://jsfiddle.net/vzj5g2sn/

Vuejs : Vue.component not seems to work

I am unsure am I doing something wrong but the vuejs component I declared is not working.
<script src="https://unpkg.com/vue"></script>
<div id="app">
<p>{{ message }}</p>
</div>
<ol>
<!-- Create an instance of the todo-item component -->
<todo-item></todo-item>
</ol>
JavaScript:
var a = new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
})
Vue.component('todo-item',
{
template: '<li>This is a todo</li>'
})
I am using the JsFiddle, message part does display the data but the todo-item didn't show anything.
Your component needs to inside your "#app" div.
<script src="https://unpkg.com/vue"></script>
<div id="app">
<p>{{ message }}</p>
<ol>
<!-- Create an instance of the todo-item component -->
<todo-item></todo-item>
</ol>
</div>
Here is a working fiddle.
Vue.component has to be called before new Vue in order for the Vue instance to use the component. From the docs (which aren't all that clear on this, admittedly):
These components are globally registered. That means they can be used in the template of any root Vue instance (new Vue) created after registration.
Vue.component('todo-item', {
template: '<li>This is a todo</li>'
})
var a = new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
})
That, and your app's code has to all be inside of the #app div, as pointed out by CUGreen's answer.

Passing object to props in a View instance > dynamically load Component from external variable

I tried with props and PropsData but it is not working :/
import Vue from 'vue'
import Hello from '#/components/Hello.vue'
export function createComponent(selector, params) {
const test = {name: 'Test'};
new Vue({
el: selector,
render: app => app(selector, {
propsData: test
})
})
}
I can't find why this is not possible even with some console.log here and there, i'm not really confident with VueJS so is there a way to do that ?
Edit:
After some testings, props was correctly passed by what I wrote, It seems that I am not correctly passing the component name to the Vue instance:
Here is how my code works (or how i want it to works at least...):
Random php file:
<?php
$selector = "Hello";
$data = json_encode(['name' => 'from PHP'])
?>
<div id="<?= $selector; ?>-component"></div>
<script>
createComponent(<?= $selector; ?>, <?php return $data; ?>) // I tried "$selector" format, but doesn't work either.
</script>
My main js file
import Vue from 'vue'
import Hello from '#/components/Hello'
export function createComponent(selector, params) {
new Vue({
el: '#' + selector + '-component',
render: app => app(selector, { // If I replace selector by Hello, it works, but that's not what I want.
props: params
})
})
}
In this file I tried some tricks to call the component from 'selector' but the console tells me: ReferenceError: Hello is not defined
But as we can see Hello is clearly define at the top of the file.
My single file vue component:
<template>
<h1>
Hello {{ name }}!!
</h1>
</template>
<script>
module.exports = {
props: {
name: {
type: String,
default: 'World'
}
}
}
</script>
I simplified my php code to show you the case so there may have some errors, I haven't tried it.
The mistake must come from the syntax, or else I get it wrong.
PS: I hate JS syntax :)
import Vue from 'vue'
export function createComponent(selector, propsData) {
let instance = new Vue({
el: document.createElement('div'),
render(createElement) {
return createElement(
'h' + this.level, // tag name
this.$slots.default // array of children
)
},
propsData
})
document.body.querySelector(selector).appendChild(instance.$el);
}
Assuming that you want to create dynamically VueJS instance and append it to dom. Also propsData object you need to move out from render function. Render function is optional, you can always use template string...

Vue.js parsing directive within vue-markdown

I am rendering an <a /> with a directive using vue-markdown.
When my App loads, it seems that my Vue instance is not parsing my rendered tag and thus not calling the appropriate directive.
I'm wondering if there is a prop i need to pass to the vue-markdown instance that will allow the Vue parser to pick up my 'nested' directive.
see example below.
import VueMarkdown from 'vue-markdown'
const Foo = Vue.directive('foo', el => console.log('Element with directive', el));
new Vue({
el: '#app',
components: { VueMarkdown },
directives: {
Foo
}
})
<template>
<div id="app">
<vue-markdown :html="true" source="<a href='/foo' v-foo>I have a directive</a>"></vue-markdown>
// ^output^ <a href="/url" v-foo>I have a directive</a>
// This <a /> is NOT registered as an element with a directive and NOT logged out.
<a href="/anotherURL" v-foo>I also have a directive</a>
// ^This^ IS registered as an alement with a directive and logged out.
</div>
</template>

Vue.js - Using Child Components in a Single File Component

I have a Vue.js app. In this app, I have a single file component. In this component, I want to have another component that's specific to the component. I'm trying to do something like this:
parent.vue
<template>
<div>
<child-component></child-component><br />
<child-component></child-component>
</div>
</template>
<script>
export default {
data() {
return {
info: 'hello'
}
},
components: {
childComponent: {
template: '<div>child</div>',
data() { return {}; }
}
}
}
</script>
After building with webpack, I then run my app in the browser. That app then generates an error in the console window that says:
Unknown custom element: - did you register the component correctly?
I believe I've set this up properly. However, clearly I haven't. What am I doing wrong? I can see where I may not have registered "child-component". However, I guess I'm not sure how to do that within a single file component. What am I missing?
Thank you,
Some ideas that might be helpful:
- as thanksd pointed out, register "child-component" intead of childComponent:
components: {
"child-component": {
template: '<div>child</div>',
data() { return {}; }
}
}
make sure you register the component before create the vue instance (this may or may not apply to your case, I cannot tell from the source code you posted:
Vue.component(child-component', {
template: 'child',
data() { return {}; }
})
new Vue({ el: '#app' })

Categories

Resources