How to comment code in a vue.js file? - vue.js

I have the need to insert a comment inside a vue.js file for future references, but I don't find how you do this in the docs.
I have tried //, /**/, {{-- --}}, and {# #}, but none of them seem to work.
I am using Laravel's blade. So this is the sample_file.vue:
<template>
<div class="media">
<like-button :post="post" v-if="post.likedByCurrentUser === false && "></like-button> {{--I want to comment this but I get an error from the gulp watch: post.canBeLikedByCurrentUser === true--}}
<div class="media-left">
<a href="#">
<img class="media-object" v-bind:src="post.user.avatar" v-bind:title="post.user.name + ' image from Gravatar'">
</a>
</div>
<div class="media-body">
<strong>{{ post.user.name }}</strong>
<p>{{post.body}}</p>
<p>{{post.likeCount}} {{ pluralize('like', post.likeCount) }}</p>
</div>
</div>
</template>
Does anyone know how to insert a comment and / or how to comment pieces of code?

You'd want to use standard HTML comments in the <template> tag in your situation. They'll be stripped from the output as well which is nice.
<!-- Comment -->

As Bill Criswell said we can use HTML comment syntax.
<!-- Comment -->
But, It will work outside the template tag too,
comment.vue
<!-- Testing comments, this will work too. -->
<template>
<!-- This will work too -->
<div>
<!-- Html Comments -->
Hello There!
</div>
</template>
<style><style>
<!-- Commenting here -->
<script>
// Commenting only 1 line
/**
* Commenting multiple lines
* Commenting multiple lines
*/
</script>

I have just tested this:
<template>
{{ /* this is a comment */ }}
<h1>Hello world</h1>
</template>

I noticed that you can't comment when you are inside a tag:
<!-- make sure it is outside a tag -->
<autocomplete
<!-- you can't place the comment out in here -->
>
</autocomplete>

If it is useful for your projects, you can put plain text above the template with no adornment. It is completely ignored when you render your component.
This is some documentation about this component
- some
- info
<template></template>
<script></script>
<style></style>

Vue Styleguidist contains best practices and shows examples of how to comment your components.
https://vue-styleguidist.github.io/docs/Documenting.html#code-comments
But in General...
In the template or HTML section use HTML comments
<!-- Comment -->
In script section use Javascript comments
// Comment
/* Comment */
In style section use CSS comments
/* comment */

The following tip is not so much about commenting (as in documenting) code per se, but rather about allowing you to temporarily skip chunks of code during development.
When comments require opening and closing tags, the way that the parser matches them can be inconvenient. For instance the following
<!-- I want to comment this <!-- this --> and that -->
will output and that -->. Similarly /* this will be commented /* and so will this */ but not this */.
My solution is to use v-if="false" to specify which blocks I want to (temporarily) skip.
<template>
<div>
Hello
<div v-if="false">
Vue will not process whatever's in here.
</div>
World!
</div>
</template>
Note that this should not be used in replacement of proper comments to document your code. It's just a convenient way to have more control over blocks that you want to skip during the development.

In Vue file / .vue use
/*-- comment in Vue file */

Depending on specific desired behavior, here are things that works to add comments in the template section:
<template>
<!-- comment incorporated in the rendered output. -->
<aside v-if="false">Some comment that won’t be in the output result.</aside>
</template>
Of course for the latter there is no requirement to use aside tag, and any false evaluated value can do the trick. So <i v-if="0">Some comment</i> will work just as well.
Admittedly, this is a bit convoluted, but Vue doesn’t seems to provide more straight forward options.

I'm noob in Vue.js, but // should work because the code is javascript anyway.
Looking in the docs I find this example. If you look the first 2 lines of javascript you will see comments with //.
example in javascript linked file:
// Full spec-compliant TodoMVC with localStorage persistence
// and hash-based routing in ~120 effective lines of JavaScript.
...

Related

how to perform the flexbox in bootstrap-vue

I am using the flex box in vue.js but the project cannot perform the functionality. the code is
<div class="d-flex">
<div class="p-2"><p>Resturants</p></div>
<div class="ml-auto p-2"><b-icon icon="three-dots-vertical"></b-icon></div>
</div>
and the output is the output image is
can you elaborate how to solve this task.
Can't comment, so i'll try to create an answer.
As other have suggested, it's strange that your box looks like this, without any css applied on.
What might be, is that the box is taking css from other components.
In every vue component, write the tag as follows
<style scoped>
this will apply the css only to that certain component.
Regarding your question, you could do something like this
<div class="row row-flex">
<div class="col-6">Content1</div>
<div class="col-6">Content2</div>
</div>
And then add your css.
Hope it helped

How to properly create a popup component in Vue 3

As part of becoming a better Vue programmer, I am trying to implement a popup similar to Popper with a clean and Vueish architecture. Here is a simple schematic that I came up with:
So basically there is a target component, which is the reference for the popup's position. The popup can be positioned above, below, right and left of the target, therefore I will need to have access to the target element in my popup. Also, the target can be an arbitrary component. It can be a simple button or span, but also something much more complex.
Then there is the popup itself, which will be put into a modal at the end of the body, It contains the actual content. The content again can be an arbitrary component.
I have a working implementation of the popup, but the basic structure seems to be far from perfect. I am using two slots, one for the target element and one for the content.
Here is what I have come up with so far for the template:
<template>
<div ref="targetContainer">
<slot name="target"></slot>
</div>
<teleport to="body">
<div v-show="show" class="modal" ref="modal">
<div ref="popover" class="popover" :style="{top: popoverTop + 'px', left: popoverLeft + 'px'}">
<slot name="content"></slot>
</div>
</div>
</teleport>
</template>
There are several issues with this that I am not really happy with.
Using the popup is not very simple
When using this popup in another component, two <template> tags are rquired. This is ungly and not very intuitive. A very simple use case looks like this:
<modal :show="showPopup" #close="showPopup=false">
<template v-slot:target>
<button #click="showPopup=true"></button>
</template>
<template v-slot:content>
<div>Hello World!</div>
</template>
</modal>
The target is wrapped in another <div>
This is done to get access to the target element, that I need for the layout. In mounted() I am referencing the target element like this:
let targetElement = this.$refs.targetContainer.children[0];
Is this really the best way to do this? I would like to get rid of the wrapping <div> element, which just asks for unintended side effects.
The best solution would be to get rid of one slot and somehow reference the target element in another way because I only need its layout information, it does not have to be rendered inside the popover component.
Can someone point me in the right direction?
Here is my solution, which was inspired by a comment on my question and which I think is worth sharing.
Instead of putting the target element into a slot, I am now passing its ref as a prop, which makes things much cleaner.
The popover component's template now looks like this.
<template>
<teleport to="body">
<div v-show="show" class="modal" ref="modal">
<div ref="popover" class="popover" :style="{top: popoverTop + 'px', left: popoverLeft + 'px'}">
<slot ref="content"></slot>
</div>
</div>
</teleport>
</template>
I has a targetRefprop, so the component can be simply used like this:
<div ref="myTargetElement" #click="isPopupVisible=true">
</div>
<modal :show="isPopupVisible" #close="isPopupVisible=false" targetRef="myTargetElement">
<!-- popup content goes here -->
</modal>
And after mounting I can access the target element like this:
let targetElement = this.$parent.$refs[this.targetRef];
I like this solution a lot. However, ideas, advice or words of caution are still highly welcome.

Creating first view in Vue.js

I'm creating first view in Vuejs like this:
<template>
<p>Welcome to MyWebsite</p>
<p>These terms and conditions outline the rules and regulations for the use of MySite Website.</p> <br />
<span style="text-transform: capitalize;"> MySite</span> is located at:<br />
<address>Adresss , City<br />State - 00000, USA<br />
</address>
</template>
But I always get
Welcome to MyWebsite These terms and conditions outline
the rules and regulations for the use of MySite Website.
MySite is located
at: Adresss , CityState - 00000, USA
Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them
instead.
why it recommend me to use v-if? I don't understand what should I do there? Regards
Component template should contain exactly one root element.
<template>
<div><!-- ONLY ONE DIRECT CHILD IN THE TEMPLATE -->
<p>Welcome to MyWebsite</p>
<p>These terms and conditions outline the rules and regulations for the use of MySite Website.</p> <br />
<span style="text-transform: capitalize;"> MySite</span> is located at:<br />
<address>Adresss , City<br />State - 00000, USA<br /></address>
</div>
</template>
For similar reasons to why React can only render a single root node Vue.js requires the first thing in the <template> to be the opening of a containing element inside of which the rest of the template will be written. Vue.js is guessing this is what you want, but it's better to make it explicit. Thus, to fix it:
<template>
<div>
<p>Welcome to MyWebsite</p>
<p>These terms and conditions outline the rules and regulations for the use of MySite Website.</p> <br />
<span style="text-transform: capitalize;"> MySite</span> is located at:<br />
<address>Adresss , City<br />State - 00000, USA<br />
</address>
</div>
</template>
The root element refers to your components root div-like element which is <template></template>
So, vue is telling you that below these root components you should only have one element: which means,
<template>
<div>
// put everything here
</div>
</template>
As stated above, you need to encapsulate the content inside a unique block (div, section...).
<template>
<section>
....
</section>
</template>

Multiple templates declared in one .vue file

I have a component inside a .vue file that can benefit from reusing a chunk of code. I know I can move that code to a separate .vue file and import it as a new component. However, this component would not be used anywhere else and I'd like to avoid cluttering the directory. Is it possible to declare this component's template inside the parent without using the in-code template:"<div>.....</div>" stuff?
This is the idea:
<template>
<div>
...some html here...
<div v-for="item in items">
{{item.name}}:
<div v-if="item.available">YES!</div>
<div v-else>NO :(</div>
</div>
...some other components and data here...
<div v-for="item in items">
{{item.name}}:
<div v-if="item.available">YES!</div>
<div v-else>NO :(</div>
</div>
</div>
</template>
I would like to be able to do something like this:
<template>
<div>
...some html here...
<div v-for="item in items">
<itemizer inline-template v-model="item">
{{value.name}}:
<div v-if="value.available">YES!</div>
<div v-else>NO :(</div>
</itemizer>
</div>
...some other components and data here...
<div v-for="item in items">
<itemizer v-model="item"/>
</div>
</div>
</template>
However, from what I understand this is not possible.
Unfortunately this pattern does not appear to be supported by the creator of Vue:
I personally feel the syntax is less maintainable than [Single File Components]
Note that we want to keep the SFC syntax as consistent possible, because it involves a big ecosystem of tools that need to support any new features added (e.g. Vetur would need to do something very different for handling SFCs with multiple scripts/templates). The proposed syntax, IMO, does not justify adding the new syntax.
https://github.com/vuejs/vue/pull/7264#issuecomment-352452213
That's too bad, as even beyond flexibility and developer choice, there is a good argument for inlining small functions that are not used by other components in order to reduce complexity. It's a common pattern in React and does not inhibit Single File Components when they're needed. In fact it allows gradual migration as inline components grow.
Here's one of the only resources currently that offers some potential workarounds:
https://codewithhugo.com/writing-multiple-vue-components-in-a-single-file/
I've tried them all and am not satisfied with any of them at this time. At best you can set runtimerCompiler: true and use template strings, but it'll add 10KB to your bundle and you'll likely miss out on full syntax highlighting available in the <template> element. Maybe you can hack Teleport, but I have not made a dedicated attempt.
Actually, this should work. Just register your Vue inline-template like this in the section of your parent .vue file:
<template>
<div v-for="item in items">
<test-template :item="item">
<h1>{{item.text}}</h1>
</test-template>
</div>
</template>
<script>
Vue.component('test-template', {
template:'#hello-world-template',
props: {
item: Object
}
});
export default {...}
</script>
In your parent HTML file, put this:
<script type="text/x-template" id="hello-world-template">
<p>Hello hello hello</p>
</script>
With vue3 there are multiple options:
with vue-jsx you can just declare a component in your script setup section and use that
const Named = defineComponent(() => {
const count = ref(0)
const inc = () => count.value++
return () => (
<button class="named" onClick={inc}>
named {count.value}
</button>
)
})
There is another option described by Michael Thiessen here
Also you can have multiple render function components in one file:
https://staging.vuejs.org/guide/extras/render-function.html
Although it is not supported in Vue core yet, there is a way to use this through vue macros project. See discussion here

Binding HTML to property (Vue.js)

How can I bind HTML to a Vue component property?
In my PHP script I have:
$html = '<div>some text</div>';
$box = "<box_includes
html_text='$html'
></box_includes>";
In my vue template:
<template id="template_box_includes">
{{ html_text }}
</template>
But in my browser I see all the text, including the tags, It's being recognized as a text:
<div>some text</div>
EDIT 2019:
Below answer is outdated as stated by #devman in the comments. Please use v-html instead:
<template v-html="html_text"></template>
Older Answer
In Vue JS, the use of the double braces are escaping HTML. You need to use three to avoid escaping html like so:
<template id="template_box_includes">
{{{ html_text }}}
</template>
You can learn more on this page of the documentation: http://vuejs.org/guide/syntax.html#Raw-HTML
I hope this helps!