Vue draggable element with a click event on it? - vue.js

I am making a Tinder clone type app in Vue. I am using the Vue2InteractDraggable component. This component works great for the use case. But I want to have a click event on the draggable portion, which does not fire (because it interprets the click as a start of a drag, as opposed to a click event).
I would like for it to use a click event if it's clicked and let go, but want it to use the current drag functionality if it's held for more than a certain amount of time. I can't figure out a way to do this, so any advice would be greatly appreciated. Here is an example of the Vue Component that I'm using. The #click on the detail section does not fire.
<Vue2InteractDraggable
v-if="cardVisible"
:interact-out-of-sight-x-coordinate="500"
:interact-max-rotation="15"
:interact-x-threshold="200"
:interact-y-threshold="9999"
#draggedRight="right()"
#draggedLeft="left()">
<div class="flex flex--center">
<img class="profilePicture" style="z-index: 4" :src="getImageSrc(current.image)"/>
</div>
<div class="rounded-borders card card--one">
<div class="userName">{{ Object.keys(this.users)[this.index] }}</div>
<div class="userAge">Age: {{current.age}}</div>
<div class="userDetailExpand" #click="expandDetails()">
<span>User Details</span>
<img class="carrot" src="../assets/svg/carrot_expand.svg"/>
</div>
</div>
</Vue2InteractDraggable>
Please let me know if you can think of any ideas. I've been hung up on this for a while and cannot find an answer.
Thank you for your help.

Try to add:
#touchstart="expandDetails()"
near:
#click="expandDetails()"

Related

How to properly create a popup component in Vue 3

As part of becoming a better Vue programmer, I am trying to implement a popup similar to Popper with a clean and Vueish architecture. Here is a simple schematic that I came up with:
So basically there is a target component, which is the reference for the popup's position. The popup can be positioned above, below, right and left of the target, therefore I will need to have access to the target element in my popup. Also, the target can be an arbitrary component. It can be a simple button or span, but also something much more complex.
Then there is the popup itself, which will be put into a modal at the end of the body, It contains the actual content. The content again can be an arbitrary component.
I have a working implementation of the popup, but the basic structure seems to be far from perfect. I am using two slots, one for the target element and one for the content.
Here is what I have come up with so far for the template:
<template>
<div ref="targetContainer">
<slot name="target"></slot>
</div>
<teleport to="body">
<div v-show="show" class="modal" ref="modal">
<div ref="popover" class="popover" :style="{top: popoverTop + 'px', left: popoverLeft + 'px'}">
<slot name="content"></slot>
</div>
</div>
</teleport>
</template>
There are several issues with this that I am not really happy with.
Using the popup is not very simple
When using this popup in another component, two <template> tags are rquired. This is ungly and not very intuitive. A very simple use case looks like this:
<modal :show="showPopup" #close="showPopup=false">
<template v-slot:target>
<button #click="showPopup=true"></button>
</template>
<template v-slot:content>
<div>Hello World!</div>
</template>
</modal>
The target is wrapped in another <div>
This is done to get access to the target element, that I need for the layout. In mounted() I am referencing the target element like this:
let targetElement = this.$refs.targetContainer.children[0];
Is this really the best way to do this? I would like to get rid of the wrapping <div> element, which just asks for unintended side effects.
The best solution would be to get rid of one slot and somehow reference the target element in another way because I only need its layout information, it does not have to be rendered inside the popover component.
Can someone point me in the right direction?
Here is my solution, which was inspired by a comment on my question and which I think is worth sharing.
Instead of putting the target element into a slot, I am now passing its ref as a prop, which makes things much cleaner.
The popover component's template now looks like this.
<template>
<teleport to="body">
<div v-show="show" class="modal" ref="modal">
<div ref="popover" class="popover" :style="{top: popoverTop + 'px', left: popoverLeft + 'px'}">
<slot ref="content"></slot>
</div>
</div>
</teleport>
</template>
I has a targetRefprop, so the component can be simply used like this:
<div ref="myTargetElement" #click="isPopupVisible=true">
</div>
<modal :show="isPopupVisible" #close="isPopupVisible=false" targetRef="myTargetElement">
<!-- popup content goes here -->
</modal>
And after mounting I can access the target element like this:
let targetElement = this.$parent.$refs[this.targetRef];
I like this solution a lot. However, ideas, advice or words of caution are still highly welcome.

<router-link> Vue Router #click event

I tried using a click event on a <router-link>. It works, but it is reloading the page everytime the link is clicked. I would like to avoid it but I can't figure out how.
I am aware that <router-link> does not accept a simple #click event. I saw on some forums that #click.I native would work, but as we know, that is deprecated.
So I would like to know if there is any solution other than wrapping the router link in a div and putting the listener on that div.
The reason why I want to do this is that I want to bind a class dinamicaly when the link is clicked. I have created a dropdown menu which is triggered onClick. But then when I follow a link inside that dropdown menu, the menu remains open. Therefore, I would like to have an additional #click event to dinamically bind a class (display: none) to the dropdown menu. The thing is that the items inside the dropdown are iterated which send parameters to a Vuex Mutation and therefore i can’t use regular tags and wrapping the router-links with a span or div is also not giving me the desired effect.
Thank you !
Regards,
T.
I have managed to solve the problem using a div wrapper and changing my css (that was preventing the code to work properly)
<div class="dropdown">
<a class="dropbtn" #click="dropClick"><i class="ri ico ri-draft-line"></i> Docs <i class="ri ico ri-arrow-drop-down-line ri-1x"></i></a>
<div class="dropdown-content" :class="{ 'dropdown-content-display': clicked }">
<div class="wrapper" v-for="route in $store.state.menuItems" :key="route.name" #click="dropClick">
<router-link :to="{ name: 'docs', params: { title: route.name } }"> <i :class="'ico ri ' + route.icon"></i> {{ route.name }}
</router-link>
</div>
</div>
</div>
If a understand your question, there is a "active-class" property on vue-router(router-link). You can set your classes dynamically by based on an active route.

Element UI Button block

I'm starting a vue js project and I decided to use Element UI which seams pretty nice.
The problem is I can't find in their documentation how to make a block button, which has the same width as the column where it is placed.
I would appreciate if you can point this out. Thank you!
Keep in mind that vue dispatches the style/class prop to the parent element of your component.
So the following should work:
<el-button style="width: 100%">Default</el-button>
You can make it by adding a full-width column in it,
like so.
<el-row>
<el-col :span="24">
<el-button type="primary"> Your Button Here </el-button>
</el-col>
</el-row>

using durandaljs hottowel - I want to change the view dynamically but activate does not let me do it

I am using Durandal, hottowel. Want to change the view dynamically, hide some div depending upon a cookie value. However, if I write the code in "activate" as such
$("#box1").hide();
$("#box2").show();
both the boxes are shown, hide does not work. But if I wire the same code to a click event then everything works. Is "activate" is not the right place to do such a thing? What's the best way to do such a thing.
My view is simply as follows:
<section>
<div id="box1">
box1
</div>
<div id="box2">
box2
</div>
</section>
A better approach is to use the knockout bindings that ship with durandal to do this declaratively in the view.
<section>
<div data-bind="visible: box1Visible">
box1
</div>
<div data-bind="visible: box2Visible">
box2
</div>
</section>
VM:
return {
activate: activate,
box1Visible: ko.observable(false),
box2Visible: ko.observable(true)
}
Then all you have to do to show or hide the boxes is set the values of those observables from the view model. The view model then doesn't need to be aware of the structure or the names of elements in the view.
I think I got the answer by using ViewAttached in my model. This method is called after view is bound. read more about it here http://durandaljs.com/documentation/Composition/
and here

dojo Expando pane content goes hidden when expanded

I have expandoPane which consists of some buttons.
When I perform other operations in the project and then expand this expandoPane, its contents goes hidden and those are visble after resizing it using splitter only.
I want to solve this.
Do you have any idea why the content goes invisible?
You need to call .startup and .resize() on the content pane when it's shown.
Something like:
expandoPane.connect(this, "onClick", function() {
that.createContent();
that.startup();
that.container.resize()
});
Post your code and I'll probably be able to give you something more specific.
Adding sample code:
<div id="expandableConsole" dojoType="dojox.layout.ExpandoPane" region="bottom" showTitle='true' maxHeight="250px" maxWidth="280px" style="height:200px; width:100%;" doLayout='true' startExpanded='false' splitter="true">
<div>
<input type="button" id="btnSubmit" style="width:88px;height:20px" onclick="update()">
</div>
<div dojoType="dijit.layout.ContentPane" id="infoBar" style="height:150px">
</div>
</div>
When I expand the expandopane after few operations,button and contentpane go invisible.