I have a Vuetify botnav; each item is activated under a certain router path, I want to inactivate the item when it's under another path.
I tried to set active.sync to -1 when I want to inactivate the tab, this will work if I never activate any item in the botnav, but if I activate an item, then set active.sync=-1 again, it will automatically activate the first item:
<v-bottom-nav
:active.sync="bottomNav"
:value="true"
shift
absolute
>
<v-btn
color="teal"
flat
value="recent"
>
<span>Recent</span>
<v-icon>history</v-icon>
</v-btn>
<v-btn
color="teal"
flat
value="favorites"
>
<span>Favorites</span>
<v-icon>favorite</v-icon>
</v-btn>
<v-btn
color="teal"
flat
value="nearby"
>
<span>Nearby</span>
<v-icon>place</v-icon>
</v-btn>
</v-bottom-nav>
In the script:
watch:{
$route:function(to, from){
switch(to.path){
case "/0":
this.bottomNav=0;
break
case "/1":
this.bottomNav=1;
break
case "/2":
this.bottomNav=2;
break
default: this.bottomNav=-1
}
}
}
I did find a solution that works, by setting a dummy hidden item in the botnav and set the v-show of this item to false, when I want to inactivate all items, I activate this unshown one, and it result in what I want:
A dummy item:
<v-bottom-nav
:active.sync="bottomNav"
//more stuff
>
//other items
<v-btn v-show="0" value="inactivate"></v-btn>
</v-bottom-nav>
And do this whenever I want to inactivate all items in the script:
this.bottomNav = "inactivate"
This WORKS, but that's kind of hacky, is there a more formal/elegant way to do this?
The default value for active.sync is undefined, so try using void to reset:
this.bottomNav = void(0)
[ https://jsfiddle.net/e8a67qtp/ ]
Related
I would like to color the combobox green under certain circumstances. I only want to color the background of the selected item green. So far, however, it colors the entire combo box. Its also enough if its only changing the text color.
<v-combobox
v-model="key"
:items="items"
:search-input.sync="search"
hide-selected
return-object
label="Search script"
persistent-hint
:class="{green : BackgroundColor }"
>
You can run your application and then use broswer to find the class of the text, overwrite the class.
eg: the className is 'combobox-text'
.combobox-text {
background: 'green' !important;
}
You can use a computed property that returns that classes that you want to attach to your element.
Example:
<script>
export default {
computed: {
comboboxClass() {
// assuming you have some prop with a boolean
return (this.myBoolean) ? {green : BackgroundColor } : undefined;
}
}
}
</script>
Then in your template use the computed property:
<v-combobox
v-model="key"
:items="items"
:search-input.sync="search"
hide-selected
return-object
label="Search script"
persistent-hint
:class="comboboxClass"
>
More information: https://v2.vuejs.org/v2/guide/class-and-style.html
I have a series of buttons with follow, unfollow status and when I click on each button, I want its status to change after a little delay and deactivation, and the button to be reactivated , For example, if the button was in the follow mode, when it was clicked, the button would be deactivated and loaded until the backend operation was performed Then change its status to unfollow.
But now with the click of a button, all the buttons change position together.
The result of my work is in the following image:
The code I wrote on the user side is as follows:
<v-btn
#click="join()"
:loading="joinGroup"
:disabled="joinGroup"
dark
v-show="joinBtn"
color="#7256EA"
class="mt-2 rounded-full bg-purple-gradient"
>Join Group
</v-btn>
The code I wrote on the back side is as follows:
<script>
data() {
return {
joinGroup: false,
}
}
methods: {
join: async function() {
this.joinGroup = true;
if (
this.group.privacy == 1 ||
(this.group.privacy == 2 && this.isFollower)
) {
this.addGroupMember(true);
} else if (this.group.privacy == 0) {
await this.addGroupMember(false);
this.sendJoinRequest();
this.snackBarPrivate();
} else if (this.group.privacy == 2 && !this.isFollower) {
this.snackBarFollowers();
}
this.joinGroup = false;
},
}
</script>
I guess your button is in a v-for and each row represents an item of your data. The problem is that each of your buttons bind to your joinGroup for :loading and :disabled, so all of them will show the state when you toggle it true.
When you are within a v-for however, you could identify which button should be disabled/loaded in connection with your item. I have made a codepen for you that shows the concept Codepen.
You could potentially also achieve this using the index in your v-for like in the following snippet.
<div v-for="(item, index) in items">
<v-btn
:disabled="disabled[index]"
:loading="loading[index]"
#click="letItLoad(index)">
Test Button
</v-btn>
</div>
I am trying to figure out how to have my dynamically generated buttons inside a for loop each have a separate loader. Vuetify has buttons with Loaders.
The problem I am having is, When these buttons are in a for loop and one is clicked they all show the loading indicator. I would like only the one that is clicked to show the loading indicator.
HTML:
<div v-for="(item, i) in items" :key='i'>
<v-btn
dark
color="pink"
:loading="loading"
#click="loader = 'loading'"
>
<v-icon>location_on</v-icon> Lookup
<span slot="loader">locating...</span>
<span slot="loader" class="custom-loader">
<v-icon dark>cached</v-icon>
</span>
</v-btn>
</div>
SCRIPT
data () {
return {
loader: null,
loading: false
}
},
Let's say I have 3 items. The code above will generate three buttons but they all will share the same loading param. How can I have each button use its only loading param? As always any and all help is much appreciated.
You're using the same data property for all buttons, so these buttons share the same loading state which affects the at one time, to make difference try to add a data property called index which represents the current clicked button index :
data () {
return {
index:-1,
loader: null,
loading: false
}
},
and bind loading prop to the condition loading && i==index and update the current index on click event #click="loader = 'loading';index=i" :
<div v-for="(item, i) in items" :key='i'>
<v-btn
dark
color="pink"
:loading="loading && i==index"
#click="loader = 'loading';index=i"
>
<v-icon>location_on</v-icon> Lookup
<span slot="loader">locating...</span>
<span slot="loader" class="custom-loader">
<v-icon dark>cached</v-icon>
</span>
</v-btn>
</div>
Its actually a lot easier than you think:
<div v-for="(item, i) in items" :key='i'>
<v-btn
dark
color="pink"
:loading="loading[index]"
#click="loading[index] = true"
>
<v-icon>location_on</v-icon> Lookup
<span slot="loader">locating...</span>
<span slot="loader" class="custom-loader">
<v-icon dark>cached</v-icon>
</span>
</v-btn>
</div>
data () {
return {
loading: {},
}
},
In the beginning loading[index] will be undefined, so it will be evaluated as false, once you establish its value in the click event it will be evaluated as true, it worked for me, hope it helps.
you can use reactive array to prevent changing the index like this.
<div v-for="(item, i) in items" :key='i'>
<v-btn #click.prevent="testload(i)" :loading="loading[i]"></v-btn>
</div>
data () {
return {
loading: [],
}
},
methods: {
testload: function (index) {
// reactive array
this.$set(this.loading, index, true);
console.log(index)
console.log(this.loading[index])
// stop loading after x miliseconds
setTimeout(() => (this.$set(this.loading, index, false)), 3000)
},
dont forget to input false according the length of items, this is the example:
getDataAll: function () {
var i = 0
for (i = 0; i < items.length; i++) {
this.loading.push(false);
}
}
Here is a ToDoList from Vue examples.
I want to add some extra features to this small app, e.g. set date for task. Therefore I'd like to show more operations of the task when I click "...".
Below is what I want to avoid, which after clicking another task, the previous click action doesn't be removed:
I try to add a property for each todo, and bind a click function on the "..." (more). Each time click "more", firstly set "isMoreClick" property of all task to false, then toggle the value of "isMoreClick" of current clicked task:
<button class="more"
#click="isMoreClick(todo)"
v-show="!todo.isMoreClick">
</button>
<div class="more-opt" v-show="todo.isMoreClick">
<button class="destroy" #click="removeTodo(todo)"></button>
</div>
...
this.todos.push({
id: todoStorage.uid++,
title: value,
completed: false,
isMoreClick: false // this is what I added
})
...
isMoreClick (todo) {
this.todos.forEach(todo => {
todo.isMoreClick = false
})
todo.isMoreClick = !todo.isMoreClick
}
I think my approach is a little stupid. Is there any better solution? (set a flag symbol?)
You don't say how you're rendering the todo elements. But if you're using a v-for loop, one approach could be
<ul>
<li
v-for="(todo, index) in todos"
:key="index"
>
{{todo.whatever}}
<button
v-if="index !== visibleTodoIndex"
class="more"
#click="visibleTodoIndex = index"
/>
<div
v-else
class="more-opt"
>
<button
class="destroy"
#click="visibleTodoIndex = -1"
/>
</div>
</li>
<ul>
Then just add visibleTodoIndex to the component's data.
It looks to me you need to use a global variable accessible from all todos, not to have a local variable inside each todo and updating it everywhere every time. I recommend using vuex store and updating isMoreClick value via mutations.
I need a 2-state toggle Button: at each tap, that changes its background color and its text label (color and text). Its implementation is simple and it works correctly when the button belongs to a simple page.
Instead, when the button is put in each element of a simple list (20 elements) it does not change its background color, and only its label text changes, not its color.
Here some code details to check the problem:
<StackLayout orientation="vertical" >
<ListView items="{{ items }}" itemTap="onItemTap">
<ListView.itemTemplate>
<StackLayout orientation="vertical" class="follow-button">
<Button text="Undefined" tap="onTap"/>
</StackLayout>
</ListView.itemTemplate>
</ListView>
</StackLayout>
and in js side ('value' not binded to a button, is used here only to demonstrate tap problem on a single button of the list):
var value = 1;
exports.onTap = function (args) {
view = args.object;
value = value === 1 ? 0 : 1;
view.text = value === 1 ? "button on" : "button off";
view.backgroundColor = value === 1 ? "red" : "white";
view.color = value === 1 ? "white" : "red";
}
I see that removing or fixing the text then background changes correctly at each tap.
Any suggestion?
I found that the fix described here seems works like a charm!
It is the only solution I found that leaves intact the app code without introduce tricks that break the philosophy behind using components.
Just put this:
Object.defineProperty(View.prototype, "isLayoutValid", {
get: function () {
return (this._privateFlags & PFLAG_LAYOUT_REQUIRED) !== PFLAG_LAYOUT_REQUIRED;
},
enumerable: true,
configurable: true
});
in
node_modules/tns-core-modules/ui/core/view/view.ios.js
And everything is magically fixed!