GeoJSON - Method within onEachFeature - vuejs2

Vue2Leaflet is a library to implement Leaflet into the Vue2 Framework; with the ability to show GeoJSON objects on a map.
With multiple GeoJSON lines, I want to have a mouse click event that effects the style of other lines (e.g. it toggles a selectedLineId variable). I managed to change the style of geojson lines on mouse over itself; see this JSFiddle.
Core is the onEachFeature which adds the mouse over event to every feature. But I have no idea how to run a Vue method from here;
function onEachFeature (feature, layer) {
layer.on('mouseover', function (e) {
e.target.setStyle({
color: "#FF0000"
});
});
layer.on('mouseout', function (e) {
e.target.setStyle({
color: "#000000"
});
});
}

You could bind your onEachFeature function to your Vue object:
data() {
return {
// ...
lines: {
geojson: geojsondata,
options: {
onEachFeature: onEachFeature.bind(this),
style: {
color: "#000000"
}
}
}
}
}
this in onEachFeature will then reference your Vue object:
function onEachFeature (feature, layer) {
var v = this;
layer.on('mouseover', function (e) {
// assuming you have a getColor method defined
e.target.setStyle({
color: v.getColor()
});
});
layer.on('mouseout', function (e) {
e.target.setStyle({
color: "#000000"
});
});
}
Here's an updated Fiddle : https://jsfiddle.net/qywaz1h8/96/

Related

Share external script between VueJS components

I am trying to load the external Stripe script in one component here https://gitlab.com/gadelkareem/skeleton/-/blob/feature/stripe/src/frontend/src/components/payment/PaymentMethods.vue#L167
this.includeStripe('js.stripe.com/v3/', function () {
this.configureStripe()
}.bind(this))
Then I load a dialog inside the same page which also needs the same Stripe() script so I have to load it again here https://gitlab.com/gadelkareem/skeleton/-/blob/feature/stripe/src/frontend/src/components/payment/AddPaymentMethod.vue#L147 with similar duplicated code.
Is there a way to share that script between both components? preferably without making it global.
You can create the init() and configureStripe() method in Vue's global context.
main.js
new Vue({
...
methods: {
init() {
this.includeStripe('js.stripe.com/v3/', function () {
this.configureStripe()
}.bind(this))
},
configureStripe () {
// eslint-disable-next-line no-undef
this.stripe = Stripe(this.pk)
this.elements = this.stripe.elements()
this.card = this.elements.create('card', {
hidePostalCode: false,
style: {
base: {
iconColor: '#666EE8',
color: '#31325F',
lineHeight: '40px',
fontWeight: 300,
fontFamily: 'Helvetica Neue',
fontSize: '15px',
'::placeholder': {
color: '#CFD7E0'
}
}
}
})
this.card.mount('#card-element')
},
}
...
});

Nuxt - Cannot access data inside a method

I'm using CKEditor 5 + CKFinder (Modal Mode) to select an image using the #click event. The problem is that I don't have access to data inside the onInit function.
Here is the method:
data() {
return {
post: {
thumbnail: null,
},
};
},
methods: {
openModal() {
console.log(this.post.thumbnail) // NO PROBLEM! this.post.thumbnail IS ACCESSIBLE
CKFinder.modal( {
chooseFiles: true,
width: 800,
height: 600,
onInit: function( finder ) {
finder.on( 'files:choose', function( evt ) {
var file = evt.data.files.first();
this.post.thumbnail = file.getUrl(); // PROBLEM !! $this.post is undefined
} );
}
} );
},
},
And this is my Template:
<div class="btn btn-danger" #click="openModal">Choose Image</div>
<img class="mx-auto d-block" :src="post.thumbnail" />
As mentioned in the comment, you need to use an arrow function to resolve this in the vue object.
Whenever you use function () {}, this refers to the properties of the function, not the Vue object that you intend to reference
// example
methods () {
openModal() {
onInit: function () {
this.post // 'this' is the onInit function, not the Vue object
}
}
}
// solution
methods () {
openModal() {
onInit: () => {
this.post // 'this' is the Vue object
}
}
}
Answer
data() {
return {
post: {
thumbnail: null,
},
};
},
methods: {
openModal() {
console.log(this.post.thumbnail) // NO PROBLEM! this.post.thumbnail IS ACCESSIBLE
CKFinder.modal( {
chooseFiles: true,
width: 800,
height: 600,
onInit: finder => {
finder.on( 'files:choose', evt => {
var file = evt.data.files.first();
this.post.thumbnail = file.getUrl(); // PROBLEM !! $this.post is undefined
});
}
});
},
},

Return value from dataPointSelection event in Apexcharts

I have a question related to this question and this answer but they don't solve my question completely. I'm using vue and apexcharts and I would like to return a value or update a variable from an event. Is it possible to return something instead of printing it in the console?
Something like this:
events: {
dataPointSelection: function (event, chartContext, config) {
this.active = this.series[config.seriesIndex];
}
}
The problem that I face is that "this" makes reference to the overall vue component and therefore "series" and "active" cannot be found.
Here is the code that gives me"TypeError: this.series is undefined" when I click on a point data. The series data I get from the parent component and it looks like this:
[{"name":"S-1","data":[[2.65,100], [6.67,100]]}, {"name":"S-2","data":[[0,50],[2.65,50]]}]
<script>
import VueApexCharts from 'vue-apexcharts';
export default {
name: "myGraph",
components: {
apexchart: VueApexCharts,
},
props: {
series: {}
},
data: () => ({
active: undefined,
chartOptions: {
chart: {
width: '100%',
animations: {
enabled: false
},
events: {
dataPointSelection: function (event, chartContext, config) {
this.active = this.series[config.seriesIndex];
}
}
},
tooltip: {
intersect: true,
shared: false
},
markers: {size: 1},
}
}),
}
}
</script>
The idea is that on dataPointSelection, it should activate that serie in order to access later on other information that will be store in that object.
The easiest way is to bind the event directly in the component
<apexchart type="bar" #dataPointSelection="dataPointSelectionHandler"></apexchart>
methods: {
dataPointSelectionHandler(e, chartContext, config) {
console.log(chartContext, config)
}
}
Another way is to use ES6 arrow functions in your chart configuration
computed: {
chartOptions: function() {
return {
chart: {
events: {
dataPointSelection: (e, chart, opts) => {
// you can call Vue methods now as "this" will point to the Vue instance when you use ES6 arrow function
this.VueDemoMethod();
}
}
},
}
}
}
I think this is simply what you are looking for
chart: {
type: 'area',
events: {
dataPointSelection(event, chartContext, config) {
console.log(config.config.series[config.seriesIndex])
console.log(config.config.series[config.seriesIndex].name)
console.log(config.config.series[config.seriesIndex].data[config.dataPointIndex])
}
}
}
if you need by the click, this is better
chart: {
type: 'area',
events: {
click(event, chartContext, config) {
console.log(config.config.series[config.seriesIndex])
console.log(config.config.series[config.seriesIndex].name)
console.log(config.config.series[config.seriesIndex].data[config.dataPointIndex])
}
}
}
source How to access value on dataPointSelection function of Apexchart
documentation events https://apexcharts.com/docs/options/chart/events/

Automatically closing Drawer when view width is decreasing

I'm trying to make a view like Firebase's console with React and material-ui.
How can I build a Drawer that will automatically close when view(browser) width is decreasing.
Quite easy, you can hook up the listener on resize event on your react class:
var RootPage = React.createClass({
render: function() {
return <Drawer refs={'drawer'} />;
},
// we trigger our drawer here
componentWillUpdate: function(nextProp, nextState) {
if(nextState.width < this.state.width) {
this.refs.drawer.open = false;
}
},
windowOnResize: function() {
var width = $(window).width();
this.setState({ width: width });
},
componentWillMount: function() {
this.windowOnResize();
},
componentDidMount: function() {
window.addEventListener("resize", this.windowOnResize);
},
componentWillUnmount: function() {
window.removeEventListener("resize", this.windowOnResize);
}
});

How to capture native event in vuejs compoent

Here is a very simple Vuejs component which attempts to capture the click event of a span:
nativeOn: {
click: function (event) {
alert('clicked')
}
},
… and here's the demo, but it does not work, what I'm missing here?
As you are registering the event on span element, you have to use on option as follows:
Vue.component('hello', {
render: function(createElement) {
return createElement("span", {
on: {
click: function(event) {
alert('clicked')
}
},
}, "Hello ")
}
})
see a live demo on jsfiddle.