I'm trying to dynamically change the css of some text in a span when a checkbox is checked using v-on:change but it is not changing and I can't figure out why.
The boolean data property "bolden" does change on-click (checked with console.log) but the class does not. the class does not even appear in the 'span' element tag when checked on devtools in chrome
here is a jsfiddle link of a piece of the code: https://jsfiddle.net/rL0fzv7s/
<script src="https://unpkg.com/vue"></script>
<div id="app">
<input type="checkbox" value="food" v-model="blog.categories" v-on:change="bolden = !bolden">
<span v-bind:class="bold">food</span>
</div>
.bold {
font-weight: bolder;
font-size: 25px;
color: red;
}
new Vue({
el: '#app',
data: {
bolden: false,
blog: {
title: "",
content: "",
categories: []
}
},
computed: {
bold: function() {
return {
bolden: this.bolden
};
}
}
})
The reason why your styles are not showing even though the value of bolden is changed is that the class name that you are using is .bold but the class name that you are returning from the computed property is called .bolden.
Change your computed bold functions's return value to the following:
computed: {
bold: function() {
return {
bold: this.bolden // class
};
}
}
You should return bold class while this.bolden true. below is the corrected code. Fiddle : https://jsfiddle.net/62mewykL/
bold: function() {
return {
bold: this.bolden
};
}
OR
Simply use v-bind:class="{'bold' : this.bolden}" in HTML
Related
I need to use vue to detect all links in the text like if i have text like this
text :
'hello mate check this link'
i want this text when it buffering in div it appear like this
'hello mate check this link'
The easiest way:
HTML
<span v-html="formattedText"></span>
Script
data() {
return {
text: 'Some kind of text with url www.google.com'
}
},
computed: {
formattedText() {
return this.linkify(this.text)
}
},
methods: {
linkify(inputText) {
const pattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&##\/%?=~_|!:,.;]*[-A-Z0-9+&##\/%=~_|])/gim;
let text = inputText.replace(pattern1, '$1');
const pattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
text = text.replace(pattern2, '$1$2');
return text;
}
It should meet your expectations, you can also change $1 and $2 in >$1|2</a> to link.
Well there are tons of libraries you could use to easily achieve this. But I personally would recommend Anchorme.js due to it's very small size. You can even customize the way the link will get handled when there are #ids & #mentions in text.
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
el: "#app",
data: function() {
return {
text: `Library works with (http://www.google.com) or without (www.google.com) protocols in link. It works well on paths [www.github.io/something/something] and queries <wordpress.com/post.php?p=112> and even when query starts immediately after the TLDS "wordpress.com?p=112".`,
convertedText: ""
}
},
computed: {
htmlText() {
const converted = anchorme({
input: this.text,
// use some options
options: {
attributes: {
target: "_blank",
class: "detected"
}
},
// and extensions
extensions: [
// an extension for hashtag search
{
test: /#(\w|_)+/gi,
transform: string =>
`${string}`
},
// an extension for mentions
{
test: /#(\w|_)+/gi,
transform: string =>
`${string}`
}
]
});
return converted;
}
}
});
.htmlText {
background-color: #eeeeee;
padding: 1em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://raw.githack.com/alexcorvi/anchorme.js/gh-pages/dist/browser/anchorme.min.js"></script>
<div id="app">
<textarea v-model="text" placeholder="enter text here" rows="3" cols="100">
</textarea>
<br/><br/>
<div class="htmlText" v-html="htmlText"></div>
</div>
How do I add my value of the prop thrID as a class value in the template?
thrID is passed in as my1value
<template>
<div v-bind:class="['hhhhh',thrID]">
test {{thrID}}
</div>
</template>
<script>
export default {
name: 'bottom',
components: {
},
props:["thrID"]
}
</script>
<style scoped>
.bottom {
background: yellow;
height: 30px;
width: 100%;
}
</style>
it renders
<div data-v-10e356bb="" data-v-7ba5bd90="" class="hhhhh">
test my1value
</div>
I want it to have a class like this
<div data-v-10e356bb="" data-v-7ba5bd90="" class="hhhhh my1value">
test my1value
</div>
You can easily add custom classes by binding a string, array or object to the class attribute. You start of by using the v-bind or : syntax to bind a variable to the class attribute:
<template>
<div :class="classes">
<!-- Magic! -->
</div>
</template>
Then, in our export component we can do several things. The most versatile option is to use an object. If the value of a key is truthy, that class is applied. If the value is falsy, it will not be applied. We use the [ keyName ]: value syntax to add this.thrID as a key to our object.
export default {
props: {
thrID: {
type: String,
required: true
}
},
computed: {
classes () {
return {
hhhhh: true,
[this.thrID]: true
}
}
}
}
Similarly, you can return an array:
classes () {
return [
'hhhhh',
this.thrID
]
}
Or you can create some string with classes:
classes () {
return `hhhhh {$this.thrID}`
}
In a blog app, I'd like to show/hide comments of each post inside a loop of posts. I know how to show the div containing the comments by setting a showComments on the fly:
this.$set(post, 'showComments', true) ;
But I don't know how to hide the post's comments when the div is already open. What I tried is this:
if (this.$get(post, 'showComments')==true) {
this.$set(post, 'showComments', false) ;
return
}
The code above thoes not work and I get this error:
Uncaught TypeError: this.$get is not a function
So I'm wondering how can I acheive this functionaliry.
You should be able to simply read the dynamic property and reapply the value.
new Vue({
el: '#app',
data() {
return {
posts: [
{ content: 'Post #1' },
{ content: 'Post #2' },
{ content: 'Post #3' }
]
}
},
methods: {
toggleComment(post) {
if ('showComment' in post) {
post.showComment = !post.showComment;
}
else {
this.$set(post, 'showComment', true);
}
}
}
})
.post {
background-color: lightgreen;
margin: 10px 0;
padding: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="post" v-for="(post, index) in posts" :key="index">
{{post.content}}
<p v-if="post.showComment">
Hidden comments.
</p>
<button #click="toggleComment(post)">Toggle comment</button>
</div>
</div>
Use property name to get property value
if ( typeof this.post.showComments !== 'undefined' && this.post.showComments ) {
Vue.set(post, 'showComments', false);
return;
}
Also note that you should try to avoid using this.$set because it was deprecated due to conflicts with other libraries. Consider using Vue.set instead.
https://v2.vuejs.org/v2/api/#Vue-set
I am learning Vue JS. I want to change class using setInterval. But can’t pass the changing value of Method to Computed Property. After two seconds class will change automatically with the changed value of "changeColor"
My Code:
HTML:
<div>
<button #click="startEffect">Start Effect</button>
<div id="effect" :class="myClass"></div>
</div>
CSS:
.highlight {
background-color: red;
width: 200px !important;
}
.shrink {
background-color: gray;
width: 50px !important;
}
Vue JS:
new Vue({
el: '#exercise',
data: {
changeColor: false
},
methods : {
startEffect: function() {
setInterval(function(){
this.changeColor = !this.changeColor;
//alert(this.changeColor);
}, 2000);
//alert(this.changeColor);
}
},
computed: {
myClass: function() {
return {
highlight: this.changeColor,
shrink: !this.changeColor
}
}
}
})
bind your function to the component...
setInterval(function(){
this.changeColor = !this.changeColor;
}.bind(this), 2000);
and then you can do ...
<div id="effect" :class="[changeColor?'highlight':'shrink']"></div>
I don't have much knowledge about child and parent component and i am just simply trying to change value in child then emit then value to parent so i can show somewhere, But it looks like not working, Not emiting the value.
This should change to : Hello from child
{{ message }} From Parent
Can anyone look this code and tell me what is mistake ?
Vue.component('child1', {
template: '<p #click="runMe">{{ display }}</p>',
props: ['display'],
data: {
display: ''
},
methods: {
runMe() {
this.display = "Hello from child"
this.$emit("changeMessage", this.display)
}
}
})
new Vue({
el: "#app",
data: {
message: "Hello 2"
},
methods: {
messageRun() {
this.message = "Change By"
}
}
})
.btnMain {
display: block;
background: #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.2/vue.min.js"></script>
<div id="app">
<button #click="messageRun" class="btnMain">Click Here</button>
<child1 :display="message" #changeMessage="message = $event"></child1>
<hr>
{{ message }} From Parent
</div>
In your code you have this where you emit:
this.$emit("changeMessage", this.display)
Change to :
this.$emit("newmessage", this.display)
I mean use lower case single word, if you use camelCase vue convert it to change-message but this is not acceptable by attribute, I tried this on your code.
After change this do this :
<child1 :display="message" #newmessage="message = $event"></child1>