Aurelia - How to access class attributes from jquery functions? - aurelia

I'm having some problems to deal with Aurelia together with jquery.
I'm trying to access the "model" in my class, from the jCrop function (which is a jquery), but I'm getting the message "model is not defined".
ModalCrop.js
export class ModalCrop{
#bindable({ defaultBindingMode: bindingMode.twoWay }) image = '';
model = {
ImageURL: this.imageBase64,
PositionX: 0,
PositionY: 0,
Width: 0,
Height: 0
};
imageChanged(newValue, oldValue){
var imageCrop = $(this.thepicture);
imageCrop.jWindowCrop({
targetWidth:500,
targetHeight:500,
onChange: function(result) {
this.model.Width = result.cropW;
}
});
}
}
HTML Component
<div class="modal-image-content">
<img ref="thepicture" src="${image}">
</div>
Someone could help me?

The problem is a problem of scope. To fix it, change the onChange function call to use a thick arrow function, like this:
onChange: (result) => {
this.model.Width = result.cropW;
}
If that doesn't work, simply add var self = this; as the first line in your imageChanged function and then change this.model.Width to self.model.Width.

Related

VueJS Leaflet 'moveend' fires multiple times

Ask for help from the community. For two weeks I can not overcome the problem with repeated firing of 'mooveend' in the project. I have tried all the advice given here. Here's what I've read and researched already, but it didn't work for me.
This is one of the tips:
moveend event fired many times when page is load with Leaflet
<template>
<div id="map"></div>
</template>
<script>
export default {
name: "ObjectMapView",
props: ['coordinate'],
data: function () {
return {
map: null,
addressPoints: null,
markers: null,
}
},
mounted: function() {
this.initializedMap();
},
watch: {
coordinate: function (val) {
this.run();
}
},
methods: {
initializedMap: function () {
this.map = L.map('map').setView([52.5073390000,5.4742833000], 13);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(this.map);
this.markers = L.markerClusterGroup();
},
run: function () {
var map = this.map;
var markers = this.markers;
var getAllObjects = this.coordinate;
var getBoundsMarkers;
//Clearing Layers When Switching a Filter
markers.clearLayers();
this.addressPoints = getAllObjects.map(function (latlng){
return [latlng.latitude, latlng.longitude, latlng.zip, latlng.object_id, latlng.archived];
});
map.addLayer(markers);
//We give to the map only those coordinates that are in the zone of visibility of the map during the first
getBoundsMarkers = getAllObjects.filter((coord) => {
if(!coord.latitude && !coord.longitude){
return false;
}
return map.getBounds().contains(L.latLng(coord.latitude, coord.longitude));
});
/*
Responds to changing the boundaries of the map visibility zone and
transmits a list of coordinates that are in the visibility zone
*/
console.log('getAllObjects_1', getAllObjects);
map.on('moveend', function() {
console.log('moveend');
console.log('getAllObjects_2', getAllObjects);
getBoundsMarkers = getAllObjects.filter((coord) => {
if(!coord.latitude && !coord.longitude){
return false;
}
return map.getBounds().contains(L.latLng(coord.latitude, coord.longitude));
});
eventHub.$emit('sendMarkers', getBoundsMarkers);
});
// In the loop, we iterate over the coordinates and give them to the map
for (var i = 0; i < this.addressPoints.length; i++) {
var a = this.addressPoints[i];
var title = '' + a[2] + ''; //bubble
var marker = L.marker(new L.LatLng(a[0], a[1]), {
title: title
});
marker.bindPopup(title);
markers.addLayer(marker);
}
eventHub.$emit('sendMarkers', getBoundsMarkers);
}
}
}
</script>
<style scoped>
#map {
width: 97%;
height: 100%;
}
</style>
I figured it out myself.
The 'zoomend' and 'dragend' option didn't work for me. I searched a lot for a suitable option and realized that the "moveend" event fires several times because this event is created every time you move the map. Therefore it is necessary to stop this event. I got out of the situation in this way. Immediately after the map was initialized, I wrote:
map.off('moveend');
and for me it worked. Now it works fine. I will be very happy if this is useful to someone.

Using dropzone.js in vue, calling function with image file name

I'm having a hard time getting anything to work with this the way I need it, but I have a working dropzone instance in my Vue project.
I can upload the image and call functions within the dropzone code, however, I need to call a function directly from the form in the html in order to send the 'card' object.
All I need to do is call a function when a file is added through the dropzone form, with the filename.
My code:
<div class="uk-width-3-10">
<form v-on:change="imageChange(card)" method="post" action="{{url('product/parts/upload/store')}}" enctype="multipart/form-data"
class="dropzone" v-bind:id="'dropzone-'+i">
</form>
</div>
...
imageChange(Card){
console.log('working');
},
addCard(){
Vue.nextTick(function () {
new Dropzone("#dropzone-"+cardIndex, {
maxFilesize: 12,
renameFile: function (file) {
var dt = new Date();
var time = dt.getTime();
return time + file.name;
},
acceptedFiles: ".jpeg,.jpg,.png,.gif",
addRemoveLinks: true,
timeout: 50000,
removedfile: function (file) {
console.log(file.upload.filename);
var name = file.upload.filename;
var fileRef;
return (fileRef = file.previewElement) != null ?
fileRef.parentNode.removeChild(file.previewElement) : void 0;
},
init: function() {
this.on("addedfile",
function(file) {
instance.imageZoneNames.push({name: file.upload.filename});
console.log(file);
console.log(instance.imageZoneNames);
});
}
});
});
}
Dropzone has many events, You used removedfile() event! there is another event called addedfile() and executes when a file is added to the dropzone list
imageChange(card) {
console.log(card)
},
addCard() {
Vue.nextTick(() => {
new Dropzone('#dropzone-` + cardIndex, {
addedfile(file) {
this.imageChange(file);
}
}
}
}

Getting reactivity from watch in Vue.js

Trying to make a component in Vue.js, which first shows image via thumbnail, loading full image in background, and when loaded, show full image.
The thing which does not work, component does not react on change of showThumb flag in watch section. What is wrong?
Vue.component('page-image',
{
props: ['data'],
template:
'<img v-if="showThumb == true" v-bind:src="thumbSrc"></img>'+
'<img v-else v-bind:src="fullSrc"></img>',
data: function()
{
return { thumbSrc: '', fullSrc: '', showThumb: true };
},
watch:
{
data: function()
{
this.thumbSrc = data.thumbImg.url;
this.fullSrc = data.fullImg.url;
this.showThumb = true;
var imgElement = new Image();
imgElement.src = this.fullSrc;
imgElement.onload = (function()
{
this.showThumb = false; // <<-- this part is broken
} );
}
}
} );
Note: there is a reason why I do it via 2 img tags - this example is simplified.
Your onload callback will have a different scope than the surrounding watch function, so you cannot set your data property like this. Change it to an arrow function to keep scope:
imgElement.onload = () =>
{
this.showThumb = false;
};
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

ViewComponent call with configuration-object

This is my first question, so please have mercy!
I am trying to Invoke the following ViewComponent:
public IViewComponentResult Invoke(MyConfiguration config)
{
return View(config);
}
My calling code looks like this:
#(await Component.InvokeAsync<MyViewComponent>(new MyConfiguration () { color: "red" }))
The ViewComponent get called, but config is null. Is anyone knowing what I have to change for it to work?
Note: I tried the code below, which worked. But creating an anonymous wrapper object seems ugly.
#(await Component.InvokeAsync<MyViewComponent>(new { config = new MyConfiguration () { color: "red" }}))
I'm always using such syntax and have no problems with that:
#await Component.InvokeAsync("MyViewComponent", new { aaa = "aaa", bbb = "bbb" })
or
#await Component.InvokeAsync("MyViewComponent", new { config = new MyConfiguration () { color: "red" }})
or
#await Component.InvokeAsync("MyViewComponent", Model.Config)

set AfterLabelTextTpl after form render

I have a form with dynamic fields. In the afterrender event of the form I want to set the afterLabelTextTpl property. I can set this property but I can't see it change in my form. How can I achieve this?
Snippet:
listeners: {
beforerender: function () {
var fields = me.getForm().getFields();
Ext.each(fields.items, function (f, idx) {
f.afterLabelTextTpl = requiredTpl;
console.log(f.afterLabelTextTpl);
}); //eo Ext.each
}
}
Edit:
I was looking for the beforerender method
Try
f.labelEl.dom.innerHTML = "LABEL:<span style='color:red;font-weight:bold' data-qtip='Required'>*</span>";
You can not use this property after the component is already rendered.
The initRenderTpl (which makes use of the label templates) method is run only if the component is not yet rendered. Once its rendered it will not run again.
You will need to update the DOM directly.
I would recomend something like this in your form:
setRequired: function(field, index) {
field.afterLabelTextTpl = requiredTpl;
},
initComponent: function(arguments) {
var me = this;
this.on('beforeadd', function(me, field){
var fields;
if (field.isXType('fieldset')) {
fields = field.query('field');
Ext.each(fields, me.setRequired);
} else {
me.setRequired(field);
}
});
// rest of logic
me.callParent(arguments);
},