i was using vue-mapbox and wanted to get an event every time theres a zoom change, is that possible with vue-mapbox? or if i can use any other alternative options?
or as an alternative if theres a click event for the <MglNavigationControl /> component which controls the zoom?
it tried adding #click on the <MglNavigationControl #click="click" /> but it doesnt work
method : {
click(){
alert('zoom button clicked')
}
}
AFAIK there's no event or action exposed in vue-mapbox for working with zoom events. You've to work around this by doing something like this:
<VueMapbox
mapStyle="mapbox://styles/mapbox/streets-v9"
accessToken="<token>"
#load="onMapLoad"
/>
methods: {
onMapLoad({ map }) {
map.on("zoomend", e => {
alert('Zoom end: ' + e.target.getZoom());
});
}
}
Related
I have been working on a website that has to function on both desktop and tablets. Part of the website is having three columns and being able to drag orders from column to column. Sometimes on drop, the user has to answer a few questions or change some of the data of that specific order. This happens in a pop-up window that is triggered by an #drop function (for example #drop="approved()". The method approved() then checks the status of the dropped order and shows the pop-up window).
When I am on desktop, everything works just fine. But when I switch to iPad Pro in the developer tools, nothing happens. I implemented Vue Draggable, which says to work with touch devices. In their examples I can't find anything about touch events or adding new handles for touch, so I don't know what to do now.
The dragging works just fine with touch devices, it's just the #drop function that doesn't trigger.
The dropzone (it includes a component that contains the draggables and a lot of if-statements):
<div class="col-md-4 border" #dragover.prevent #drop="approved()">
<Wachtrij class="fullHeight" :data2="opdrachtenData2"></Wachtrij>
</div>
The method:
export default {
methods: {
...
approved() {
console.log("Function approved() is being executed.")
if (this.draggingOrder.status === 5) {
this.popupGekeurd = true;
}
else if (this.draggingOrder.status === 6) {
this.popupTochGoed = true;
}
else if ([40, 52, 42,41,49,55,54].indexOf(this.draggingOrder.status) !== -1) {
this.back = true;
}
},
...
}
}
The problem seems to be that you are using native events, while the touch implementation does not (always?) use these events. It is intended that you use a draggable component with one of the events outlined in the documentation. In your case the start and end events look promising. This event has a few properties (docs), some of them being to and from.
Let's assume that we have the following code:
<draggable v-for="(zone, index) in zones" v-model="zones[index]" :class="['dropzone', `zone-${index}`]" :key="`dropzone-${index}`" :options="options" #start="start" #end="end">
<div v-for="item in zones[index]" class="dropitem" :key="`dropitem-${item.id}`">
{{ item.title }}
</div>
</draggable>
This creates a few zones, each filled with their own items. Each array item of zones is changed based on where you move each item. You can then use start to have information on when you start moving an item, and end to have information on when you stop moving an item, and where that item came from and where it ended up. The following methods show off what you can do with that in this case:
methods: {
start (event) {
console.log('start', event);
},
end (event) {
console.log('end', event);
const { from, to } = event;
if (to.className.match(/\bzone-2\b/)) {
console.log('Zone 2 has something added!')
}
if (from.className.match(/\bzone-0\b/)) {
console.log('Zone 0 had something removed!');
}
}
}
We make our dropzones with a class zone-0, zone-1 or zone-2 in this case, so we can use the class name to determine which dropzone we ended up in.
An alternative way to determine which zone was changed is to simply use a watcher. Since zones changes based on where you move items, you can simply watch a particular dropzone for changes and do things based on that.
watch: {
'zones.1': {
handler (oldZone, newZone) {
if (Array.isArray(oldZone) && Array.isArray(newZone) && oldZone.length !== newZone.length) {
console.log('Zone 1 was changed from', oldZone, 'to', newZone);
}
}
}
}
A full example can be found on codesandbox.
I am using vue 2.1.10.
I am using #contextmenu event to detect on right click events.
But I want to detect right click up and down events.
How can I do that?
As of v2.2, you can listen for right mouse click events using the right modifier (and prevent the default behavior of the contextmenu event by using the prevent modifier):
<button
#mousedown.right="mousedown"
#mouseup.right="mouseup"
#contextmenu.prevent
>
Click Me
</button>
Here's a working fiddle.
If you aren't using v2.2 or above, you can manually check for the right mouse click using the which property of the click event instead:
<button
#mousedown="mousedown"
#mouseup="mouseup"
#contextmenu.prevent
>
Click Me
</button>
methods: {
mousedown(event) {
if (event.which === 3) {
console.log("Right mouse down");
}
},
mouseup(event) {
if (event.which === 3) {
console.log("Right mouse up");
}
}
}
Here's a working fiddle.
I have set up the aurelia-dialog plugin. It's working using the example in the GitHub readme, but the documentation doesn't explain anything about how to use it otherwise. I have a simple use case with a list page. I want to click an "add new" button, pop the modal dialog which has it's own VM. The modal contains a simple dropdown list. I need to select an item on the list and make an API call to save the data, but I can't seem to figure out how to wire up my save method with the save button on the dialog.
The method that opens the dialog on my list page (which works just fine):
loadAgencyDialog(id){
this.dialogService.open({ viewModel: AddAgency, model: { id: id }}).then((result) => {
if (!result.wasCancelled) {
console.log('good');
console.log(result.output);
} else {
console.log('bad');
}
});
My modal add-agency.js (VM for the modal, also loads the select list just fine and yes, I have a variable named kase because case is reserved):
import {DialogController} from 'aurelia-dialog';
import {ApiClient} from 'lib/api-client';
import {inject} from 'aurelia-framework';
#inject(DialogController, apiClient)
export class AddAgency {
kase = { id: '' };
constructor(controller, apiClient){
this.controller = controller;
this.agencies = [];
this.apiClient = apiClient;
}
activate(kase){
this.kase = kase;
this.apiClient.get('agencies')
.then(response => response.json())
.then(agencies => this.agencies = agencies.data)
.then(() => console.log(this.agencies)); //these load fine
}
addAgency() {
//Do API call to save the agency here, but how?
}
}
This is part I'm unsure about. In the example, they use controller.ok(theobjectpassedin), which returns a promise. But I don't get where I can call my addAgency method. Any ideas?
It's possible I'm misunderstanding your question, but you should be able to just call addAgency() in your HTML:
<button click.trigger="addAgency()">Add</button>
And then do what you need to do in addAgency(), finishing with a call to this.controller.ok() to wrap up the modal.
As an example, here's my modal's dialog-footer:
<ai-dialog-footer>
<button click.trigger="controller.cancel()">Cancel</button>
<button click.trigger="ok(item)">Save</button>
</ai-dialog-footer>
And in my code:
ok(item) {
this.controller.ok(item);
}
Not too complex. Hope that helps.
I am using getItemTextTpl to add a checkbox component to a nested list - I would also like to be able to override the default tap event so that when the checkbox is checked a popup message shows and the list does not advance to the next items. Please see below for my configuration - I am able to capture the checkbox check event but do not no how to override the default behavior for nestedlist. Thanks for your help and please let me know if I can clarify any details - if it helps I am using sencha architect
Nestedlist config:
getItemTextTpl: function(recordnode) {
return '<table width="100%"><row>' +
'<tr><td width="100%" align="left" width="100%" valign="bottom"><div class="view"><input type="checkbox" <tpl if="done">checked</tpl> /> {name}</td></row></table>';
}
Controller:
onNestedlistInitialize: function(component, options) {
// setup taskList to listen on the tap on the checkbox and show a popup window
component.element.on({
tap: function(e, el) {
console.log('checkbox tapped');
//need to override nestedlist tap event and show popup message
}
});
To prevent the list from switching to the next card you need to override the activeitemchange like so :
var nestedList = Ext.create('Ext.NestedList', {
...
listeners:{
activeitemchange:function(){
if(...){ // Check if you checkbox is checked or not
return false; // return false prevent the nestedlist from switching to the next view
}
}
}
});
I've been following along with a Railscast tutorial of backbone.js and I wanted to extend the functionality to include keyboard control. I added the following to my show view:
class Raffler.Views.EntryShow extends Backbone.View
template: JST['entries/show']
events:
'click .back': 'showListing'
'keyup': 'goBack'
showListing: ->
Backbone.history.navigate("/", trigger: true)
goBack: (e) ->
console.log e.type, e.keyCode
render: ->
$(#el).html(#template(entry: #model))
this
On my show template I have the following:
Back
<%= #entry.get('name') %></td>
If I select the back link using the tab key, then start hitting random keys I get output in my javascript console. However if I load the page and do not select the link and just start hitting keys I get no output in my console.
How do I bind the event to the document so that it will listen to any keys pressed when loading the screen?
You will need to work around backbone's scope for views.
when you are doing something like this:
events:
'click .back': 'showListing'
'keyup': 'goBack'
you are binding your goBack function to the keyup event raised on your container element of your view. (by default the div in which the view is rendered)
instead of doing that, if you want to bind to something outside your view (which doesn't have it's own view!(*))
Raffler.Views.EntryShow = Backbone.View.extend({
template: JST['entries/show'],
events: {
'click .back': 'showListing'
},
initialize: function () {
$('body').keyup(this.goBack);
},
showListing: function () {
Backbone.history.navigate("/", trigger: true);
},
goBack: function (e) {
console.log e.type, e.keyCode;
},
render: function () {
$(this.el).html(this.template(entry: #model));
return this;
}
});
(*)remark as marked above, you best do this only when the item you want to bind to does not have it's own view, if you have a view for your full page (an app view or something like that) you could bind the keyup in there, and just raise an event App.trigger('keypressed', e); for example.
you can then in your EntryShow view, bind to that App's keypressed event.
App.bind('keypressed', goBack);
keep in mind that you should do something as a delayed event or grouping keypresses together in some situations, as firing every keypress that happens in the body, might be a big performance hit. especially on older browsers.
Your events will be scoped to your view element #el. To capture events on the document, you have to roll that yourself:
initialize: ->
$(document).on "keyup", #goBack
remove: ->
$(document).off "keyup", #goBack
Should do the trick.