I want to add a preLoaders to vue-loader options.
I looked at this document https://cli.vuejs.org/guide/webpack.html#modifying-options-of-a-loader
That's my code
config.module
.rule("vue")
.use("vue-loader")
.tap((options) => {
return {
preLoaders: {
addCommonTemplate: function (source, map) {
console.log("addd", source, map);
this.callback(null, source, map);
},
},
};
});
It went error
I changed a way
config.module
.rule("vue")
.use("vue-loader")
.tap((options) => {
options.preLoaders = {
addCommonTemplate: function (source, map) {
console.log("addd", source, map);
this.callback(null, source, map);
},
};
return options;
});
It run successfully but not logged. It didn't work.
I don't know how to modify vue-loader options.
Related
Every time the Map is loading i am calling 500ms after finished the loading process the this.map.invalidateSize()-Method to try to clean the map view up.
But also when I am loading this, the map still appears like this:
What do i have to do, that the map loads directly in my location or at least in the defined center with the defined zoom-Level?
Is there any event, that I can listen for on Angular/Leaflet, which indicates, that the map has loaded properly and also the loaded KML-Data is loaded?
EDIT
The following code is producing this error. Please take note, that i have removed unused content, which is not relevant for this problem (like adding a marker to the map).
ngOnInit() {
this.initMap();
}
processBaseLayers() {
this.layerControl = L.control
.layers(this.layerControl, null, {
position: 'bottomright',
})
.addTo(this.map);
let defaultLayerSet = false;
this.baseLayers.forEach((layer) => {
const baseLayer = new L.TileLayer(layer.serverURL, {
maxZoom: layer.maxZoom,
attribution: layer.attribution,
});
if (!defaultLayerSet) {
baseLayer.addTo(this.map);
defaultLayerSet = true;
}
this.layerControl.addBaseLayer(baseLayer, layer.name);
});
}
fixMapOccurences() {
setTimeout(() => { this.map.invalidateSize() }, 500)
}
async initMap() {
this.map = L.map('map', {
center: [46.947222222222, 7.4441666666667],
zoom: 12,
zoomControl: false,
});
this.map.whenReady(() => {
this.processBaseLayers();
setTimeout(async () => {
this.fixMapOccurences();
await this.loadKML();
}, 1000)
});
}
async loadKML() {
this.dataLayers.forEach((dataLayer) => {
const kmlLayer = omnivore.kml(dataLayer.serverURL).on('ready', () => {
kmlLayer.eachLayer((layer) => {
if (layer.feature.geometry.type === 'Point') {
// adding point here
} else if (layer.feature.geometry.type === 'GeometryCollection') {
// adding polyline here
}
});
});
});
}
I've been trying to create a custom widget for Netlify CMS to allow for key-value pairs to be inserted. However there are a few things going wrong, I'm thinking they might be related so I'm making a single question about them.
This is my first custom widget, and I’m mostly basing this on the official tutorial: https://www.netlifycms.org/docs/custom-widgets/
I’m using a Map as the value, but when I add a new element to the map, and then call the onChange(value) callback, nothing seems to happen. However, if I change it to onChange(new Map(value)) it does update. It seems that the onChange callback requires a new object?
Secondly, the value doesn’t seem to be actually saved. When I fill in other widgets and refresh the page, it then asks to restore the previous values. However it doesn’t restore the map, while restores the other values just fine.
And lastly, I get uncaught exception: Object like a second after I change anything to the map. My guess is that Netlify CMS is trying to save the map (debouncing it for a second so it doesn’t save every letter I type), but fails and throws that exception. That would explain the previous problem (the non-saving one).
My complete code for the custom widget currently is:
var IngredientsControl = createClass({
getDefaultProps: function () {
return {
value: new Map()
};
},
addElement: function (e) {
var value = this.props.value;
value.set("id", "Description");
//is.props.onChange(value);
this.props.onChange(new Map(value));
},
handleIdChange: function (oldId, newId) {
console.log(oldId, newId);
var value = this.props.value;
var description = value.get(oldId);
value.delete(oldId);
value.set(newId, description);
//this.props.onChange(value);
this.props.onChange(new Map(value));
},
handleDescriptionChange: function (id, description) {
console.log(id, description);
var value = this.props.value;
value.set(id.toLowerCase(), description);
//this.props.onChange(value);
this.props.onChange(new Map(value));
},
render: function () {
var value = this.props.value;
var handleIdChange = this.handleIdChange;
var handleDescriptionChange = this.handleDescriptionChange;
var items = [];
for (var [id, description] of value) {
var li = h('li', {},
h('input', { type: 'text', value: id, onChange: function (e) { handleIdChange(id, e.target.value); } }),
h('input', { type: 'text', value: description, onChange: function (e) { handleDescriptionChange(id, e.target.value); } })
);
items.push(li);
}
return h('div', { className: this.props.classNameWrapper },
h('input', {
type: 'button',
value: "Add element",
onClick: this.addElement
}),
h('ul', {}, items)
)
}
});
var IngredientsPreview = createClass({
render: function () {
var value = this.props.value;
var items = [];
for (var [id, description] of value) {
var li = h('li', {},
h('span', {}, id),
h('span', {}, ": "),
h('span', {}, description)
);
items.push(li);
}
return h('ul', {}, items);
}
});
CMS.registerWidget('ingredients', IngredientsControl, IngredientsPreview);
What am I doing wrong?
Thanks!
I solved this by using immutable-js's map: https://github.com/immutable-js/immutable-js
when user get close to some area on map, display specific data from one other function? I am calculating average of each area estate prices in computed functions. it's below. you can see the average function on jsfiddle...
Already displaying averages but, what I need to do here, when user get zoomed in that region/city then display that areas average... The original code with map down below...
For example, how to sets bounds and connect those bounds to average function??? Thank you for helping.!
code updated!
data() {
return {
avg:"",
map: {},
mapName: "map",
estates: [],
},
mounted() {
axios.get('/ajax').then((response) => {
this.estates = response.data
});
this.initMap();
},
methods: {
initMap: function(){
var mapOptions =
{
zoom : 6,
center : {
lat:34.652500,
lng:135.506302
}
};
this.map = new google.maps.Map(document.getElementById(this.mapName), mapOptions);
google.maps.event.addListener(this.map, 'bounds_changed', function() {
console.log("bound changed alert");
});
},
avgArray: function (region) {
const sum = arr => arr.reduce((a,c) => (a += c),0);
const avg = arr => sum(arr) / arr.length;
return avg(region);
},
},
computed: {
groupedPricesByRegion () {
return this.estates.reduce((acc, obj) => {
var key = obj.region;
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(obj.m2_price);
return acc;
}, {});
},
averagesByRegion () {
let arr = [];
Object.entries(this.groupedPricesByRegion)
.forEach(([key, value]) => {
arr.push({ [key]: Math.round(this.avgArray(value)) });
});
return arr;
},
},
I don't think this is specific to vue, its more about google-maps.
You can listen to the bounds_changed event on the map object: bounds_changed
And then get the boundaries of your current view
Have a look at this excellent answer which should help you out.
If you are using vuejs, you an look at this library vue-google-maps which should help you out.
P.S make sure to debounce the function you call on bounds_changed or you may make a lot of unnecessary calls to your generating-averages function
I am making a vue project and I want to use leaflet inside of my components. I have the map showing but I run into an error when I try to add a marker to the map. I get
Uncaught TypeError: events.forEach is not a function
at VueComponent.addEvents (VM2537 Map.vue:35)
at e.boundFn (VM2533 vue.esm.js:191)
at HTMLAnchorElement. (leaflet.contextmenu.js:328)
at HTMLAnchorElement.r (leaflet.js:5)
<template>
<div>
<div id="map" class="map" style="height: 781px;"></div>
</div>
</template>
<script>
export default {
data() {
return {
map: [],
markers: null
};
},
computed: {
events() {
return this.$store.state.events;
}
},
watch: {
events(val) {
this.removeEvents();
this.addEvents(val);
}
},
methods: {
addEvents(events) {
const map = this.map;
const markers = L.markerClusterGroup();
const store = this.$store;
events.forEach(event => {
let marker = L.marker(e.latlng, { draggable: true })
.on("click", el => {
store.commit("locationsMap_center", e.latlng);
})
//.bindPopup(`<b> ${event.id} </b> ${event.name}`)
.addTo(this.map);
markers.addLayer(marker);
});
map.addLayer(markers);
this.markers = markers;
},
removeEvent() {
this.map.removeLayer(this.markers);
this.markers = null;
}
},
mounted() {
const map = L.map("map", {
contextmenu: true,
contextmenuWidth: 140,
contextmenuItems: [
{
text: "Add Event Here",
callback: this.addEvents
}
]
}).setView([0, 0], 1);
L.tileLayer("/static/map/{z}/{x}/{y}.png", {
maxZoom: 4,
minZoom: 3,
continuousWorld: false,
noWrap: true,
crs: L.CRS.Simple
}).addTo(map);
this.map = map;
}
};
</script>
New2Dis,
Here is your example running in a jsfiddle.
computed: {
events: function () {
return this.store.events;
}
},
watch: {
events: function (val) {
this.removeEvents();
this.addEvents(val);
}
},
methods: {
addEvents(events) {
console.log("hoi")
const map = this.map;
const markers = L.markerClusterGroup();
const store = this.$store;
events.forEach(event => {
let marker = L.marker(event.latlng, { draggable: true })
.on("click", el => {
//store.commit("locationsMap_center", event.latlng);
})
.bindPopup(`<b> ${event.id} </b> ${event.name}`)
.addTo(this.map);
markers.addLayer(marker);
});
map.addLayer(markers);
this.markers = markers;
},
removeEvents() {
if (this.markers != null) {
this.map.removeLayer(this.markers);
this.markers = null;
}
}
},
I did replace some things to make it works, like the $store as I don't have it, and removeEvent was not written correctly, so I'm not sure what I actually fixed...
I have also created a plugin to make it easy to use Leaflet with Vue.
You can find it here
You will also find a plugin for Cluster group here
Give it a try and let me know what you think.
I want to add a custom property to fabricjs.IText, i used a same script i used with my fabricjs.Text class:
fabric.CustomIText = fabric.util.createClass(fabric.IText, {
type : 'custom-itext',
initialize : function(element, options) {
this.callSuper('initialize', element, options);
options && this.set('textID', options.textID);
},
toObject: function() {
return fabric.util.object.extend(this.callSuper('toObject'), {textID: this.textID});
}
});
fabric.CustomIText.fromObject = function(object) {
return new fabric.CustomIText(object.text, object);
};
fabric.CustomIText.async = false;
When I create my new custom-itext there is no problem.
var text = new fabric.CustomIText('NewText', { left: 0, top: 0 , fill: color, fillColor:color, textID: "SommeID"});
canvas.add(text);
But whene I want to load my new CustomItext from a JSON i have a javascrip error:
Uncaught TypeError: Cannot read property 'async' of undefined
Thank you
Here's a code saving additional attributes in serialization for any object on canvas. This might solve your problem, it worked for me
// Save additional attributes in Serialization
fabric.Object.prototype.toObject = (function (toObject) {
return function () {
return fabric.util.object.extend(toObject.call(this), {
textID: this.textID
});
};
})(fabric.Object.prototype.toObject);
I got it to work with async initialization:
fabric.TextAsset = fabric.util.createClass(fabric.IText, {
type: 'textAsset',
initialize: function(element, options) {
this.callSuper('initialize', element, options);
this.set('extraProp', options.extraProp);
},
toObject: function() {
return fabric.util.object.extend(this.callSuper('toObject'), {
extraProp: this.get('extraProp')
});
}
});
fabric.TextAsset.fromObject = function (object, callback) {
callback(new fabric.TextAsset(object.text, object));
};
fabric.TextAsset.async = true;
}