How to short-circuit v-model in custom directives? - javascript

I want to have a custom directive I can attach to any <input> which will limit it to alpha chars only. Here's what I have so far:
https://jsfiddle.net/m473tpfu/
It works, however, the Vue.js docs state:
Apart from el, you should treat these arguments as read-only and never modify them.
So modifying vnode is a bad pattern. How can I achieve this differently?

You could do it like this: your directive has an input handler that checks whether forbidden chars are included, and if so, strips them out and issues a new input Event so that everything updates.
The usual issue of cursor moving to the end of the field when you rewrite its value applies.
Vue.directive('limiter', {
inserted(el, binding, vnode) {
el.addEventListener('input', event => {
const newValue = event.target.value;
const cleaned = newValue.replace(/[^A-Za-z]/g, '');
if (newValue !== cleaned) {
event.target.value = cleaned;
event.target.dispatchEvent(new Event('input'));
}
});
}
});
new Vue({
el: "#app",
data() {
return {
name: '',
};
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
<script src="//unpkg.com/vue#latest/dist/vue.js"></script>
<div id="app">
<input v-model="name" v-limiter />
<div>
Your name is {{ name }}.
</div>
</div>

Related

Preventing refresh page on submit in React

I'm trying to create an editable table that will turn a specific cell in to an <input> once it's clicked and then will run the handleSubmit() method once the user presses return.
Below is an example of a <td> cell using an onClick event to run handleClick() method and turn it's <td></td> in to <form><input></input></form>.
<td onClick={ e => this.handleClick(e)} style={{padding:'5px'}} key={cellID} id={cellID}>{frame.rows[i][idx]}</td>
handleClick(e:React.MouseEvent<HTMLTableDataCellElement, MouseEvent>) {
if(this.state.editing == false){
let form = `<form onSubmit=${ (e:any) => {this.handleSubmit(e)} } ><input type="text" value=${e.currentTarget.innerText} className="input-small gf-form-input width-auto"/></form>`
e.currentTarget.innerHTML = form;
}
this.setState({editing: true})
}
handleSubmit(e){
e.preventDefault()
}
Using e.preventDefault() does not seem to work in this instance. Every time i press return after changing the text, the page refreshes. How do i stop the page from refreshing in this instance?
I'm guessing you're wanting to achieve something where you can editing columns, modify or abandon changes, and then update things as needed.
This example is with local state, but you could still do it with fetching data.
Click the "Run code snippet" below to see a working example.
// main.js
const { useState } = React;
const App = () => {
// State
const [data, setData] = useState([{ id: 1, name: 'John', editing: false }, { id: 2, name: 'Kevin', editing: false }]);
// Functions
const onSubmitForm = index => event => {
// To prevent form submission
event.preventDefault();
// To prevent td onClick
event.stopPropagation();
const newData = [...data];
newData[index].name = newData[index].temp;
newData[index].editing = false;
delete newData[index].temp;
setData(newData);
}
const onClickToggleEditing = index => event => {
// To prevent td onClick and button conflicting with each other for toggling back on
event.stopPropagation();
const newData = [...data];
newData[index].editing = !newData[index].editing;
newData[index].temp = newData[index].name;
setData(newData);
}
const onInputChange = index => event => {
const newData = [...data];
newData[index].temp = event.target.value;
setData(newData);
}
// Render
// This basically like having its own component
const editing = ( data, index, onChange, onSubmit, onCancel) => {
const onKeyUp = index => event => {
if (event.key === 'Escape') {
onCancel(index)(event);
}
}
return <form onSubmit={onSubmit(index)}><input onKeyUp={onKeyUp(index)} onClick={e => e.stopPropagation()} type="text" value={data.temp} placeholder="Enter text" onChange={onChange(index)} /><button onClick={onSubmit(index)} type="submit">Save</button><button type="button" onClick={onCancel(index)}>Cancel</button></form>
}
return <main>
<h1>Table Editing</h1>
<p><small>Click to edit cell for <b>Name</b>.</small></p>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
{data && data.length > 0 && <tbody>
{data.map((i, k) => <tr key={`row-${k}`}>
<td>{i.id}</td>
<td className="editable" onClick={onClickToggleEditing(k)}>{i.editing ? editing(i, k, onInputChange, onSubmitForm, onClickToggleEditing) : i.name}</td>
</tr>)}
</tbody>}
</table>
<hr />
<p><b>Data Manipulation:</b></p>
<pre><code>{JSON.stringify(data, null, '\t')}</code></pre>
</main>
}
ReactDOM.render(<App />, document.querySelector('#root'));
body {
padding: 0;
margin: 0;
font-family: Arial,sans-serif;
}
main {
padding: 0 20px;
}
h1 {
font-size: 18px;
}
table {
width: 100%;
border-spacing: 0;
}
table tr td,
table tr th {
border: 1px solid #efefef;
height: 30px;
line-height: 30px;
text-align: left;
padding: 6px;
}
table tr th:first-child {
width: 100px;
}
.editable:hover {
background: #efefef;
cursor: pointer;
}
table input {
height: 30px;
line-height: 30px;
font-size: 14px;
padding: 0 6px;
margin-right: 6px;
}
table button {
height: 32px;
border: none;
background: red;
color: white;
font-size: 14px;
padding: 0 10px;
border-radius: 4px;
margin-right: 5px;
cursor: pointer;
}
table button[type=submit] {
height: 32px;
border: none;
background: green;
color: white;
font-size: 14px;
padding: 0 10px;
border-radius: 4px;
}
hr {
border: none;
height: 1px;
background: #999;
margin: 20px 0;
}
pre {
background: #efefef;
padding: 6px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
There are a few issues in your code. I'd better fix them, rather than trying to fix the issue with the form submission. And once it is done, you won't have to fix the issue with the form - there simply won't be any.
First, let's take a look into your editable cell:
<td onClick={ e => this.handleClick(e)} style={{padding:'5px'}} key={cellID} id={cellID}>{frame.rows[i][idx]}</td>
This element should be rendered differently, based on some state. We can achieve this easily with React:
// JSX snippet
<td onClick={ e => this.handleClick(e)}
style={{padding:'5px'}}
key={cellID} id={cellID}>
{this.state.editing ? <Input ... /> : <Label ... />}
</td>
I do not provide all the code, because I believe the components are self-explainable (and you are welcome to name them as you'd like to, I give them very simple names to make their aim clear).
<Input /> encapsulates everything related to editing logic
<Label /> simply renders a text or whatever you need (probably frame.rows[i][idx])
... means that they will most probably have some values/handlers passed as props
In your code, you have this:
let form = `<form onSubmit=${ (e:any) => {this.handleSubmit(e)} } ><input type="text" value=${e.currentTarget.innerText} className="input-small gf-form-input width-auto"/></form>`
I believe it deserves to be a separate component with its own state and logic (e.g. submit). In fact, this is what <Input ... /> is in my example. And if you make it as a separate component - the following code will work (because it will be a part of that separate component):
handleSubmit(e) {
e.preventDefault()
}
Finally, avoid doing something like that:
e.currentTarget.innerHTML = form;
Reconsider your approach and you simply won't need to do something like that.
hi you can use it like below:
1- i assume you have a return button like below so you can submit in return not using form submit event:
_handleReturn(){
let val = document.getElementById("your input id");
//you can post above text to server if you want
//Do Somthing
}
<button id="btn_return" onClick={this._handleReturn} />
2- i don't see where you trigger handleSubmit, but submitting form cause refresh, you should use ajax if you don't want.

Reactive object in 2 arrays

I have an array of objects (array 1), that can be toggled to another array (array 2). When added the user has the option to type in a text field for each option. The toggling works fine and is reactive on the initial creation. But if I have data that already exists in array 2, the item is no longer reactive.
I have made a quick jsfiddle to demonstrate: Event 1 and 3 are reactive, but event 2 no longer is as it already exists in the newEvents array. Is there anyway to get this connected to the original event?
new Vue({
el: "#app",
data: {
events: [
{ id: 1, text: "Event 1"},
{ id: 2, text: "Event 2"},
{ id: 3, text: "Event 3"}
],
savedEvents: [
{ id: 2, text: "Event 2", notes: 'Event Notes'}
]
},
methods: {
toggleEvent: function(event){
let index = this.savedEvents.findIndex(e => e.id == event.id);
if (index != -1) {
this.savedEvents.splice(index, 1);
} else {
this.savedEvents.push(event);
}
},
inArray: function(id) {
return this.savedEvents.some(obj => obj.id == id);
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
.btn {
display: inline-block;
padding: 5px;
border: 1px solid #666;
border-radius: 3px;
margin-bottom: 5px;
cursor: pointer;
}
input[type=text]{
padding: 5px;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Events:</h2>
<ol>
<li v-for="event in events">
<span class="btn" #click="toggleEvent(event)">
{{ event.text }}
</span>
<input type="text" placeholder="Type your note here..." v-model="event.notes" v-if="inArray(event.id)">
</li>
</ol>
<h2>
Saved Events:
</h2>
<ul>
<li v-for="event in savedEvents">
<strong>{{ event.text }}</strong> {{ event.notes }}
</li>
</ul>
</div>
The problem here is nothing to do with reactivity.
When you add an event to newEvents by clicking the button it's using the same object that's in events. As there's only one object for each event everything work fine.
In the case of Event 2 you're starting with two separate objects representing the same event, one in events and the other in newEvents. Changes to one will not change the other.
It's difficult to say what the appropriate solution is here without knowing your motivation for choosing these data structures but the example below ensures that both arrays contain the same object for Event 2.
The only thing I've changed from your original code is the data function.
new Vue({
el: "#app",
data () {
const data = {
events: [
{ id: 1, text: "Event 1"},
{ id: 2, text: "Event 2", notes: 'Event Notes'},
{ id: 3, text: "Event 3"}
],
newEvents: []
}
data.newEvents.push(data.events[1])
return data
},
methods: {
toggleEvent: function(event){
let index = this.newEvents.findIndex(e => e.id == event.id);
if (index != -1) {
this.newEvents.splice(index, 1);
} else {
this.newEvents.push(event);
}
},
inArray: function(id) {
return this.newEvents.some(obj => obj.id == id);
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
.btn {
display: inline-block;
padding: 5px;
border: 1px solid #666;
border-radius: 3px;
margin-bottom: 5px;
cursor: pointer;
}
input[type=text]{
padding: 5px;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Events:</h2>
<ol>
<li v-for="event in events">
<span class="btn" #click="toggleEvent(event)">
{{ event.text }}
</span>
<input type="text" placeholder="Type your note here..." v-model="event.notes" v-if="inArray(event.id)">
</li>
</ol>
<h2>
New Events:
</h2>
<ul>
<li v-for="event in newEvents">
<strong>{{ event.text }}</strong> {{ event.notes }}
</li>
</ul>
</div>
There are various ways you could represent this data other than by using two lists of the same objects. You might use a boolean flag within the objects. Or you could use a separate object to hold the notes, keyed by event id. It's difficult to know what would work best for your scenario.
Update:
Based on the comments, you could do something like this to use the objects in events as canonical versions when loading savedEvents:
loadSavedEvents () {
// Grab events from the server
someServerCall().then(savedEvents => {
// Build a map so that the objects can be grabbed by id
const eventMap = {}
for (const event of this.events) {
eventMap[event.id] = event
}
// Build the list of server events using the objects in events
this.savedEvents = savedEvents.map(savedEvent => {
const event = eventMap[savedEvent.id]
this.$set(event, 'notes', savedEvent.notes)
return event
})
})
}
As pointed out by #skirtle the object from the list array needs to be pushed into the second array for it to be reactive. I have solved this by looping through and matching the id and then pushing this object into the second array. Not sure if this is the best / most efficient way to do this but it works now.
new Vue({
el: "#app",
data: {
eventsList: [
{ id: 1, text: "Event 1"},
{ id: 2, text: "Event 2"},
{ id: 3, text: "Event 3"}
],
savedEvents: [
{ id: 2, text: "Event 2", notes: 'Event Notes'}
]
},
mounted() {
this.init();
},
methods: {
init: function() {
let _temp = this.savedEvents;
this.savedEvents = [];
_temp.forEach(event => {
this.eventsList.forEach(x => {
if (event.id == x.id) {
this.$set(x, "notes", event.notes);
this.savedEvents.push(x);
}
});
});
},
toggleEvent: function(event){
let index = this.savedEvents.findIndex(e => e.id == event.id);
if (index != -1) {
this.savedEvents.splice(index, 1);
} else {
this.savedEvents.push(event);
}
},
inArray: function(id) {
return this.savedEvents.some(obj => obj.id == id);
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
.btn {
display: inline-block;
padding: 5px;
border: 1px solid #666;
border-radius: 3px;
margin-bottom: 5px;
cursor: pointer;
}
input[type=text] {
padding: 5px;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Events:</h2>
<ul>
<li v-for="event in eventsList">
<span class="btn" #click="toggleEvent(event)">
{{ event.text }}
</span>
<input type="text" placeholder="Type your note here..." v-model="event.notes" v-if="inArray(event.id)">
</li>
</ul>
<h2>
Saved Events:
</h2>
<ul>
<li v-for="event in savedEvents">
<strong>{{ event.text }}</strong> {{ event.notes }}
</li>
</ul>
</div>
Try using $set and $delete for avoiding reactivity lost
https://v2.vuejs.org/v2/api/?#Vue-set
https://v2.vuejs.org/v2/guide/reactivity.html

How can I block some characters in a textarea with VueJs?

I have a textarea for sending messages and I wanna block emails and site links. So when I write an # or https:// there must be error messages shown, using v-if, but how can I do this? Which functions?
new Vue({
el: "#app",
data: {
message: {
content: ""
}
},
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>
<textarea v-bind="message" v-model="message.content" cols="30" rows="10">
</textarea>
<p v-if="message.content == '#'">
No special characters
</p>
</div>
</div>
You can check by regex type , for your condition var regex = /(#|https)/g; . Also set hasError data for message display control and you can use vue watch for your data changing (message.content)
new Vue({
el: "#app",
data: {
message: {
content: ""
},
hasError: false
},
watch: {
'message.content': function(newVal,oldVal) {
var regex = /(#|https)/g;
this.hasError = newVal.match(regex);
}
}
})
body {
background: #20262E;
padding: 10px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 10px;
transition: all 0.2s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>
<textarea v-bind="message" v-model="message.content" cols="30" rows="5">
</textarea>
<p v-if="hasError">
No special characters
</p>
</div>
</div>
i think you should add method #change or #input to textarea, and then test for everything using regex and than replace it or whatever you want to do

How to update data on a page without refreshing on the vue.js?

My view is like this :
<div class="favorite" style="margin-bottom:5px;">
#if (Auth::user())
<add-favorite-store :id-store="{{ $store->id }}"></add-favorite-store>
#else
<a href="javascript:" class="btn btn-block btn-success">
<span class="fa fa-heart"></span> Favorite
</a>
#endif
</div>
My component is like this :
<template>
<a href="javascript:" class="btn btn-block btn-success" #click="addFavoriteStore($event)">
<span class="fa fa-heart"></span> <label id="favoriteId">{{ store_id == 'responseFound' ? 'Un-Favorite' : 'Favorite' }}</label>
</a>
</template>
<script>
export default{
props:['idStore'],
mounted(){
this.checkFavoriteStore()
},
methods:{
addFavoriteStore(event){
var label = $('#favoriteId')
var text = label.text()
event.target.disabled = true
const payload= {id_store: this.idStore}
if(text == "Favorite") {
this.$store.dispatch('addFavoriteStore', payload)
}
else {
this.$store.dispatch('deleteFavoriteStore', payload)
}
setTimeout(function () {
location.reload(true)
}, 1500)
},
checkFavoriteStore(){
const payload= {id_store: this.idStore}
var data = this.$store.dispatch('checkFavoriteStore', payload)
data.then((res) => this.store_id = res)
}
},
data() {
return {
store_id: ''
}
}
}
</script>
On the my code above, I using
location.reload(true)
to update data on the page. But it's reload the page.
I want when update the page, it's not reload the page
How can I do it?
Ok Here is a simple use case but less complicated as yours and using vuejs as it should be used. (http://codepen.io/simondavies/pen/MJOQEW)
OK let laravel/php code get the store ID as well as if its already been favorited. This way your script is not first checking the store to then decide what to do.
What this does is sends the store-id and the is-favorited through the component like:
<favorite :store-id="{{$store->id}}" :is-favorited="{{$store->isFavorited}}"></favorite>
Then the Vue component will update the button to display if its already liked (red) or not (grey), and then also handle the click event and update accordingly as well.
As you are using Laravel to tell the component if it's already favorited you can get rid of your checking function and one less http request. Then you only need to then update the store when the user clicks the favourite button.
And as seen in the demo it updates, no need to refresh.
I hope this help you re-write yours so you get waht you want.
PS i have left out the Logged IN check #if (Auth::user()) you have so you can put that back in etc
Vue.component('favorite', {
template: '<button type="button" #click.prevent="updateFaviteOption" :class="{ \'is-favorited\': isFavorited }"><span class="fa fa-heart"></span></button>',
props: [
'storeId',
'isFavorited'
],
data: function() {
return {}
},
methods: {
updateFaviteOption: function() {
this.isFavorited = !this.isFavorited;
///-- DO YOU AJAX HERE i use axios
///-- so you can updte the store the the this.isFavorited
}
}
});
new Vue({
el: '#app',
});
.favorite-wrapper {
margin: 20px auto;
padding: 0;
text-align: center;
width: 500px;
height: 100px;
}
a:link,
a:active,
a:visited {
text-decoration: none;
text-transform: uppercase;
color: #444;
transition: color 800ms;
font-size: 18px;
}
a:hover,
a:hover:visited {
color: purple;
}
button {
margin: 10px auto;
padding: 8px 10px;
background: transparent;
width: auto;
color: white;
text-transform: uppercase;
transition: color 800ms;
border-radius: 4px;
border: none;
outline: none;
}
button:hover {
cursor: pointer;
color: #058A29;
}
.fa {
color: #d9d9d9;
font-size: 20px;
transition: color 400ms, transform 400ms;
opacity: 1;
}
.is-favorited .fa {
opacity: 1;
color: red;
transform: scale(1.4);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css" rel="stylesheet" />
<div id="app">
<div class="favorite-wrapper">
<favorite :store-id="3" :is-favorited="true">
</favorite>
</div>
</div>
Another solution explained in vue-router doc. Simply use the watch system applied to the $route native attribute. You'll be able to detect new route even if they use the same component and fetch the data in consequence.
What you need is vm-forceUpdate.
Force the Vue instance to re-render. Note it does not affect all child components, only the instance itself and child components with inserted slot content.
I haven't tried using this myself, just came across it while working on a project.
vue forceUpdate or you could just call the function in the setTimeout method.
setTimeout(function () {
this.checkFavoriteStore();
}, 1500)
You are using a lot of javascript here, you can use vue to do most of the work there.

How to toggle a selected class in a global click event?

I'm creating my component library in vue, and I defined my component checkbox, the code is like this:
<template>
<div class="checkboxcont" :class="{'checkboxcont-selected': isSelected}" #click="clickevent">
<span class="j-checkbox">
<input type="checkbox" />
</span>
<slot></slot>
</div>
</template>
<script>
export default {
data() {
return {
isSelected: false
}
},
methods: {
clickevent(event) {
if(this.isSelected) {
this.isSelected = false;
} else {
this.isSelected = true;
}
}
},
}
</script>
Now, I hope that when I click the checkbox to set the data "isSelected" false, I can give the component class "checkboxcont-selected-last", and when I click other checkbox component, the classname "checkboxcont-selected-last" can be removed, how can I listen my click event to finish it? I try to use native JavaScript code to add the classname of the dom, but it seemed to have nothing when I binded the classname of my component with Vue.js:
clickevent(event) {
if(this.isSelected) {
this.isSelected = false;
this.$el.classList.add("checkboxcont-selected-last");
} else {
this.isSelected = true;
}
}
What should I do to solve this problem, please?
Here is my style code using less:
<style lang="less" scoped rel="stylesheet/less">
#import '../../mixin/mixin.less';
.checkboxcont {
display: inline-block;
&:hover {
cursor: pointer;
.j-checkbox {
border-color: #jbluelight;
}
}
}
.j-checkbox {
position: relative;
top: 0;
left: 0;
width: 12px;
height: 12px;
display: inline-block;
border: 1px solid #border;
border-radius: 3px;
line-height: 12px;
vertical-align: -3px;
margin: 0 5px;
z-index: 20;
transition: all .2s linear;
input {
opacity: 0;
position: absolute;
left: 0;
top: 0;
visibility: hidden;
/*display: none;*/
}
}
.checkboxcont-selected {
.j-checkbox {
background: #jbluelight;
border-color: #jbluelight;
&:after {
content: '';
width: 4px;
height: 7px;
border: 2px solid white;
border-top: none;
border-left: none;
position: absolute;
left: 3px;
top: 0;
z-index: 30;
transform: rotate(45deg) scale(1);
}
}
}
</style>
<style lang="less" rel="stylesheet/less">
#import '../../mixin/mixin.less';
.checkboxcont-selected-last .j-checkbox {
border-color: #jbluelight;
}
</style>
My initial thought is that I add the class by using this.$el after I clicked the component, it can be accessed because I dispatched the click event, and I just can't access the other component:
if(this.isSelected) {
this.isSelected = false;
this.$el.classList.add("checkboxcont-selected-last")
} else {
this.isSelected = true;
}
And I remove the class by using native HTML DOM operation when I dispatch the click event because I can not access the other component, so the complete definition of clickevent is that:
clickevent(event) {
let selectedLast = document.querySelector(".checkboxcont-selected-last");
if(selectedLast) {
selectedLast.classList.remove("checkboxcont-selected-last")
}
if(this.isSelected) {
this.isSelected = false;
this.$el.classList.add("checkboxcont-selected-last")
} else {
this.isSelected = true;
}
}
It looks good, but I can not add classname of my component when I use v-bind to bind my component's classname, is it wrong? And Is it unable to use native HTML DOM operation when I bind my component's classname with Vue?
A better way to dynamically add or remove class can be using v-bind:class. There are different ways you can add a dynamic class based on a vue data variable.
I see you are already using it:
<div class="checkboxcont" :class="{'checkboxcont-selected': isSelected}" #click="clickevent">
So here this div will have only one class : checkboxcont if isSelected is false, and two classes : checkboxcont and checkboxcont-selected if isSelected is true.
Edited:
Given that you want to add a class to DOM on another component, I can think of two ways:
Using Web API: You can do following if you know the id of the element you want to add class using Element.className:
var d = document.getElementById("yourElem") d.className += " otherclass"
Vuex way: You can have a centralised state provided by vue or use vuex to manage state, these state variables can be changed across components, and can be used to add/remove class dynamically.
You can have a look at my this answer to understand more about vuex.

Categories

Resources