I want to show a button ONLY if two conditions are met. First I try v-if with only one condition at a time:
v-if="editMode"
v-if="$can('customersdelete')"
using only one condition at a time, the button is display, so i think both conditions are true. If i use:
v-if="editMode && $can('customersdelete')"
The button isn't display. $can is a mixin, to validate user has permission to do something.
<script>
export default {
methods: {
$can(permissionName) {
return Permissions.indexOf(permissionName) !== -1;
},
},
};
</script>
I don't know why this is not working...
Apparently, any subsequent v-if is ignored and only the first one is taken into account, as demonstrated by the following example:
Vue.config.devtools = false;
Vue.config.productionTip = false;
const Permissions = ['customersdelete'];
new Vue({
el: '#app',
data() {
return { editMode: true };
},
methods: {
$can(permissionName) {
return Permissions.indexOf(permissionName) !== -1;
},
},
})
code {
background-color: #f5f5f5;
border: 1px solid #eee;
padding: 2px 5px;
color: red;
border-radius: 3px;
display: inline-block;
}
div {
margin-top: 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<label><input type="checkbox" v-model="editMode">editMode</label><br><br>
<div>$can('customersdelete') => <code v-text="$can('customersdelete')"></code></div>
<div>editMode => <code v-text="editMode"></code></div>
<hr />
<div v-if="$can('customersdelete')">
<code>v-if="$can('customersdelete')"</code>
</div>
<div v-if="editMode">
<code v-if="editMode">v-if="editMode"</code>
</div>
<div v-if="editMode && $can('customersdelete')">
<code>v-if="editMode && $can('customersdelete')"</code>
</div>
<div v-if="editMode"
v-if="$can('customersdelete')">
<code>v-if="editMode" v-if="$can('customersdelete')"</code>
</div>
<div v-if="$can('customersdelete')"
v-if="editMode">
<code>v-if="$can('customersdelete')" v-if="editMode"</code>
</div>
</div>
I would suggest use function and then use in v-if.
example
v-if="isButtonShow()"
and below is the method portion:
methods:{
isButtonShow(){
if(this.editMode){
if(this.$can('customersdelete'){
return true;
}
}
return false;
}
}
Related
Why does it happen that my Vue router navigates to /#/! without apparent reason?
This seems to happen when I fire an event from an autocomplete form built with Bootstrap Autocomplete and trigger a function.
Calling the same function by clicking a button does not lead to the problem.
This is the parent component where the event is emitted to
<style scoped>
</style>
<template>
<div id="appspace">
<div id="leftbar">
</div>
<div id="workarea">
<div id="mapblock">
</div>
<div id="infoblock">
<div class="form-group"><label for="gotoff">Go to</label>
<autosuggest #locselect="locSelect($event)" id="gotoff"></autosuggest>
</div>
<button v-on:click="searchAround()" type="button" class="btn btn-primary">Search</button>
</div>
</div>
<div id="rightbar">
</div>
</div>
</template>
<script>
module.exports = {
data: function () {
return {
};
},
components: {
autosuggest: httpVueLoader('components/base/autosuggest.vue'),
},
mounted: function(){
},
destroyed: function(){
},
methods: {
setMarkerInCenter: function(){
this.locSelect({ value: { lng: 12, lat: 14 }})
},
locSelect: function(e) {
console.log('locSelect');
console.log(e);
},
},
}
</script>
and this is the component emitting the event:
<style scoped>
.autocomplete {
position: relative;
width: 130px;
}
.autocomplete-results {
padding: 0;
margin: 0;
border: 1px solid #eeeeee;
height: 120px;
overflow: auto;
}
.autocomplete-result {
list-style: none;
text-align: left;
padding: 4px 2px;
cursor: pointer;
}
.autocomplete-result:hover {
background-color: #4AAE9B;
color: white;
}
</style>
<template>
<div class="input-group">
<input ref="ac" class="form-control">
<div class="input-group-append">
<div class="input-group-text"><i class="fa fa-compass" style="height:0.5em;padding:0;margin:0;margin-bottom:4px"></i></div>
</div>
</div>
</template>
<script>
module.exports = {
mounted: function(){
var i = this.$refs.ac;
var c = this
$(i).autoComplete({ resolverSettings: { url: '/api/gc/autocomplete' } });
$(i).on('autocomplete.select', function(e, sel) {
e.preventDefault();
c.$emit('locselect', sel);
e.preventDefault();
});
},
}
</script>
Any leads as to how to debug this?
I couldn't find the reason why this autocomplete changes the route, that behavoir
seems to be undocumented. But here's a method to temporarily prevent this behavior until you find the solution, add this global route guard to your router to prevent navigation to '/#/!' route:
router.js
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
console.log(to)
// TEMP PATCH:
// Autocomplete changes route to '/#/!'
if (to.path !== '/#/!') {
next()
}
})
Just make sure that console.log(to) actually has a property path === '/#/!'
I have a preloader in Vue js but it's infinite, how could I fix it? I was thinking about doing something to hide the div that contains the preloader when the page is loaded using mounted(), but I am not sure what should I do exactly. I am working in the App.vue file.
EDIT: Tried to add the class d-none when the component is mounted but that didn't work
new Vue({
el: "#app",
data(){
return{
classes: '',
}
},
mounted(){
this.classes='d-none';
}
});
/* Loader */
#preloader {
position: fixed;
left: 0;
top: 0;
z-index: 99999;
width: 100%;
height: 100%;
overflow: visible;
display: table
}
.loader {
display: table-cell;
vertical-align: middle;
position: relative;
width: 200px;
height: 200px
}
#preloader,
.contact-box,
.scroll-to-top {
background: #fff;
text-align: center
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div id="preloader" v-bind:class="classes">
<div class="row loader">
<img src="https://media2.giphy.com/media/3oEjI6SIIHBdRxXI40/giphy.gif" alt="logo" width="220" height="110">
<br><br>
</div>
</div>
<h1>content</h1>
</div>
the best way to do this task in vuejs is using a v-if.
e.g
<div v-if="!isLoaded" id="preloader">
<div class="row loader">
<img src="https://media2.giphy.com/media/3oEjI6SIIHBdRxXI40/giphy.gif" alt="logo" width="220" height="110">
<br><br>
</div>
</div>
new Vue({
el: "#app",
data(){
return{
isLoaded: false,
}
},
mounted: function() {
this.$nextTick(q => {
// Will be executed when the DOM is ready
this.isLoaded = true;
// UPD : you can use this instead for your tests ..
// setTimeout(function () { this.isLoaded = true; }, 2000)
})
}
});
I have an input box that takes a string. Can I execute a method (in vue.js) when the length of the string gets to a certain number?
something like
<input v-if="inputBox.length == 6 THEN runme()"...>
You can use watch option, you'll be able to react to data changes :
new Vue({
el: '#root',
data: {
message: '',
inputLength : undefined
},
methods : {
doSomething(){
console.log('I did it !')
}
},
watch :{
message : function(val) {
if(val.length>=5){
this.inputLength = val.length
this.doSomething();
}
}
}
})
.container {
padding-top: 2em;
}
.intro {
font-size: 1.5em;
margin-bottom: 1.5em;
}
.input-value {
margin-top: 1em;
font-size: 1.25em;
}
.highlight {
color: #00d1b2;
font-weight: bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div class="container">
<h1 class="intro">Binding with Vue</h1>
<div id='root' class="box">
<label class="label">Enter text here</label>
<input class="input is-medium" type='text' id='input' v-model='message'>
<p class="input-value">The value of the input is: <span class="highlight">{{ inputLength }}</span></p>
</div>
</div>
In this example, if input length is >= 5 then it will change the inputLenght value in data and execute a method.
For more informations about this, go see :
https://v2.vuejs.org/v2/guide/computed.html#Watchers
You can use a watcher to trigger a method when the string exceeds the length:
new Vue({
data () {
return {
model: ''
}
},
watch: {
model: {
handler: function (value) {
if (value.length >= 6) {
this.trigger()
}
}
}
},
el: '#app',
methods: {
trigger () {
alert('hi there')
}
},
template: `<input v-model="model">`
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>
I am facing an issue.
I am currently working on a framework agnostic element library with the new browser API customElements.define() and created a custom input and would like him to work with v-model binding.
But, it does not work. I am able to bind a value with :value="prop" but v-model simply does not work.
class LmTag extends HTMLElement {
constructor() {
super();
this.template = document.querySelector("#lmTag");
this.shadow = this.createShadowRoot();
this.clone = document.importNode(this.template.content, true);
this.shadow.appendChild(this.clone);
this.input = this.shadow.querySelector('input');
}
connectedCallback() {
this.value = this.getAttribute("value");
}
get value() {
return this.input.value;
}
set value(value) {
this.input.value = value;
}
attributeChangedCallback(attr, oldValue, newValue) {
console.log(attr, oldValue, newValue);
}
}
customElements.define("lm-tag", LmTag);
Vue.config.productionTip = false
Vue.config.devtools = false;
new Vue({
el: '#app',
data: {
lights: true,
input: "model"
},
methods: {
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template id="lmTag">
<style>
.lm-tag {
display: inline-block;
padding: 4px;
border-radius: 4px;
background-color: #e74c3c;
color: #ffffff;
font-size: 12px;
}
.lm-tag input {
border: none;
}
</style>
<span class="lm-tag">
<input type="text"/>
<content></content>
</span>
</template>
<div id="app" class="text-center body">
<p>
Binding :value
<lm-tag :value="input">{{input}}</lm-tag>
</p>
<p>
Binding v-model
<lm-tag v-model="input">{{input}}</lm-tag>
</p>
<p>
Raw input with :value
<input type="text" :value="input">
</p>
<p>
Raw input with v-model
<input type="text" v-model="input">
</p>
</div>
Could you help a fellow dev having trouble with his code?
Thank you!
Assign filename to input field on upload and then show success message working fine,but when i try to delete file and upload again it's not working!
new Vue({
el: "#app",
data() {
return {
form: {
message: '',
fileurl: ''
},
loading: false
}
},
methods: {
uploadImage(event) {
this.form.fileurl = 'uploaded!'
},
deleteFile(furl) {
this.form.fileurl = ''
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
span {
color: red;
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<h3>
File Upload / remove Demo
</h3>
<hr />
<div class="custom-file attach_file" v-show="!form.fileurl">
<input type="file" id="file" name="file" #change="uploadImage($event)">
<input type="text" v-model="form.fileurl">
</div>
<p v-if="form.fileurl"> {{ form.fileurl }} <span #click="deleteFile(form.fileurl)">Delete</span></p>
</div>
I am not getting any console error as well.
This is what i have tried so far.
Can you guys please have a look at this!
The problem is that #change is not trigger when you choose the same file. The simplest solution is reset value of input when you click delete
this.$refs.fileToUpload.value = '';
new Vue({
el: "#app",
data() {
return {
form: {
message: '',
fileurl: ''
},
loading: false
}
},
methods: {
uploadImage(event) {
this.form.fileurl = 'uploaded!'
},
deleteFile(furl) {
this.form.fileurl = ''
this.$refs.fileToUpload.value = '';
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
span {
color: red;
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<h3>
File Upload / remove Demo
</h3>
<hr />
<div class="custom-file attach_file" v-show="!form.fileurl">
<input type="file" id="file" name="file" class="custom-file-input" #change="uploadImage($event)" ref="fileToUpload">
<input type="text" v-model="form.fileurl">
</div>
<p v-if="form.fileurl"> {{ form.fileurl }} <span #click="deleteFile(form.fileurl)">Delete</span></p>
</div>
You need to clear you input field first.
Update your upload method with this.
uploadImage(event) {
this.form.fileurl = 'uploaded!'
this.success = false
this.$nextTick(() => {
this.success = true
})
Have a look at this working demo
https://jsfiddle.net/asimshahzad/8c9pcfys/