Display Vue Bootstrap b-tooltip only if b-button is disabled - vue.js

A b-button is conditionally disabled if the user is an admin. Right now, a b-tooltip displays when hovering over it and it is not disabled.
Is there a way to display the tooltip only if it is disabled?
I've tried adding the v-bind, a v-if, id:disabled, and multiple variations of those on the button and tooltip, to no avail.
<form ref="form" #click="handleDelete">
<b-button v-bind:disabled="userRole !== 'admin'" id="tooltip-target-1" variant="danger">
Admin Delete Agency
</b-button>
<b-tooltip target="tooltip-target-1" triggers="hover">
You cannot delete an agency with children. Reassign child agencies to continue deletion.
</b-tooltip>
</form>

To hide the tooltip when the button is enabled, use v-if
<form ref="form" #click="handleDelete">
<b-button v-bind:disabled="userRole !== 'admin'" id="tooltip-target-1" variant="danger">
Admin Delete Agency
</b-button>
<b-tooltip v-if="userRole !== 'admin'" target="tooltip-target-1" triggers="hover">
You cannot delete an agency with children. Reassign child agencies to continue deletion.
</b-tooltip>
</form>
And to make the tooltip work on a disabled button, check out this section of bootstrap vue docs.

I added a v-if on the tooltip and a span wrapping the button. Thanks #Romalex
<form ref="form" #click="handleDelete">
<span id="disabled-wrapper" class="d-inline-block" tabindex="0">
<b-button v-bind:disabled="userRole !== 'admin'" style="pointer-events: none;" variant="danger">
Admin Delete Agency
</b-button>
</span>
<b-tooltip v-if="userRole !== 'admin'" target="disabled-wrapper" triggers="hover">
You cannot delete an agency with children. Reassign child agencies to continue deletion.
</b-tooltip>
</form>

Related

HTMX: disable click event on child nodes

I have the following divs and want that when clicking on id="child" it should NOT execute a get to "/modal/closed" and NOT replace the id="modal". That is, do nothing HTMX related.
<div id="modal" hx-trigger="click"
hx-swap="outerHTML" hx-target="#modal" hx-get="/modal/closed" hx-params="none">
<div id="child">
</div>
</div>
Right now I have it working using the trigger "click consume" but need to specify an hx-get to an HTTP path that returns nothing (/nop).
Is there a cleaner way to do this?
<div id="modal" hx-trigger="click"
hx-swap="outerHTML" hx-target="#modal" hx-get="/modal/closed" hx-params="none">
<div hx-trigger="click consume" hx-swap="none" hx-get="/nop">
</div>
</div>
This can be solved using the event modifier "target:#modal" to indicate we are only interested on the click event originated from the id="modal".
This way clicks over id="child" that bubble up to id="modal" will be ignored.
<div id="modal" hx-trigger="click target:#modal"
hx-swap="outerHTML" hx-get="/modal/closed" hx-params="none">
<div id="child">
</div>
</div>
It works this way due to attribute inheritance in htmx https://htmx.org/docs/#inheritance. Placing the hx-trigger attribute on the outer-most div, means that element will listen for the event in all of it's children. When you add the same attribute to a child div with the consume modifier it stops the event bubbling up.
So the solution here would be to remove the hx-trigger from the outer div. In fact, if what you are trying to do is close a modal, you can add a close button somewhere else in the div. Something like this:
<div id="modal">
<button id="close" hx-trigger="click"
hx-swap="outerHTML" hx-target="#modal" hx-get="/modal/closed" hx-params="none">Close</button>
<div id="child">
</div>
</div>
Now when you click on the child div the event bubbles up and it's not caught by the sibling close button.

How to set router-link for a component except some parts

I've created a card using VueJS & tailwind. There are some buttons on the card like edit & delete. I want to add a router-link on this Card Component, so that when a user clicks on the card, it opens up, but then the edit and delete buttons don't work any more and clicking on them, redirects the page too.
How can I solve this problem?
Here is my code:
<router-link to="somewhere">
<card-component :data="products"></card-component>
</router-link>
Card Component:
<div :key="id" v-for="(row, id) in data">
<div>
<img alt="Product Image"
v-lazy="row.img_url"
class="vs-images-hover-zoom rounded-lg p-0 h-24 w-32 object-center object-cover"/>
</div>
<div>
<p class="product-name font-medium">{{ row.name }}</p>
</div>
<div class="whitespace-no-wrap">
<feather-icon icon="EditIcon" svgClasses="w-5 h-5 hover:text-primary stroke-current" #click="editPopup = true"/>
<feather-icon icon="TrashIcon" svgClasses="w-5 h-5 hover:text-danger stroke-current" class="ml-2" #click="deletePopup = true"/>
</div>
</div>
Seems like you're having trouble with event handling because button's clicks are being caught by router-link. You can do one of them:
Use #click.stop in your buttons inside the Card component (it will stop event propagation);
Don't use router-link wrapping the whole card and put it just on image and title elements, for example;
Don't use router-link at all and get the #click event in right peaces of card, using this.$router.push to handle it.

Vue-Multiselect Plugin: How to safely remove "add a new" tag functionality?

I am using a plugin called Vue-Multiselect and have it working pretty good on my app. However, there is a functionality in the plugin that I do no want. How can I safely remove it?
Let me explain: CodeSandBox Collaboration Editor .
Note: To see this flow in action, choose EDIT next to ACME Widget and then search for an on existent user in the multiselect input box.
When a user is searched for in the multiselect input box, and if a match is found, the match pops up for the user to select. That is good. However, when a user is NOT found, there's a placeholder text that says the following: Press enter to create a tag . I do NOT want to give my users the ability to create new tags/options if the option does not exist. How can I remove that functionality from this component?
Here is my multi-select component code:
<multiselect
id="customer_last_name_input"
v-model="values"
:options="options"
label="lastname"
placeholder="Select or search for an existing customer"
track-by="uid"
:loading="isLoading"
:custom-label="customerSelectName"
aria-describedby="searchHelpBlock"
selectLabel
:multiple="true"
:taggable="true"
>
<template
slot="singleLabel"
slot-scope="props"
>{{ props.option.lastname }}, {{props.option.firstname}}</template>
<template slot="option" slot-scope="props">
<strong>{{ props.option.lastname }}</strong>
, {{ props.option.firstname }} —
<small>{{ props.option.email }}</small>
</template>
<!-- <template slot="noResult">Looks like this customer doesn't exist yet.<button class="btn btn-primary" type="button" #click="addCustomer">Add Customer</button></template> -->
</multiselect>
I found the answer. I simply remove the taggle=true prop from the multiselect component.

VUEJS List items editable with button #click (button is in another component)

I need to make list items editable on click.
I have a template with a card displaying the list items, and a button component that contains, among others, a button that will trigger modify(). When this button is clicked the list items should become text inputs and a save button should appear at the bottom.
I read about contentEditable = true, but I don't know where to set it. If it's #click, the button component needs to be aware of the list items.
How to let the button know about those list items?
<button /> should be child of <detailActivity>... so Props?
Here's the template with the list items: <detailActivity />
<b-row>
<b-card
header-tag="header"
footer-tag="footer"
class="text-center"
>
<h3 slot="header" class="mb-0">Activity Details</h3>
<ul
v-for="value in currentActivity"
:key="value.id"
class="listValues">
<li>....</li>
<li>....</li>
<li>....</li>
</ul>
<div slot="footer">
<buttons />
</div>
</b-card>
</b-col>
<b-col xs="8">
<activity-map />
</b-col>
</b-row>
Inside the <button /> component, among others, the edit button:
<b-button
variant="warning"
#click="edit"
>
Any idea on how I should do this?
THANKS

how to pass index to sibling div/tag

I'm developing a mobile app using phonegap, vuejs2 and onsenui. I installed vue2-touch-events plugin for touch events. In this app i'm rendering some data using v-for. Here is the div.
<v-ons-list-item class="swipeArea"
v-for="(list, index) in todoLists"
v-bind:key="list.todo"
v-if="!list.completed"
v-touch:swipe.left="deleteLisItem(index)"
v-touch:swipe.right="doneLisItem(index)"
v-touch:longtap="deleteOrDone(index)" tappable>
<label class="center">
<i class="zmdi zmdi-check" aria-hidden="true"></i> {{ list.todo }}
</label>
</v-ons-list-item>
And then when user longtap a list there will be a pop with 3 button. Done, Delete and cancel. When user tap done, the item will be mark as done, if click delete, the item will be deleted and click cancel will cancel the event. Here is the div
<div v-if="doneOrDelete" id="doneOrDelete">
<div class="action-sheet-mask"></div>
<div class="action-sheet">
<button class="action-sheet-button" #click="doneLisItem">Done</button>
<button class="action-sheet-button action-sheet-button--destructive" #click="deleteLisItem">Delete</button>
<button class="action-sheet-button" #click="doneOrDelete=false">Cancel</button>
</div>
</div>
Now all i have to do is pass the index to the method. Can anyone help me how pass the index? TIA