How I could dispatch a custom event from '#input1' in this function?
What i tried:
export function captcha1_verified() {
$w('#input1').show();
const myEvent = new CustomEvent("myevent", {
detail: {},
bubbles: true,
cancelable: true,
composed: false,
});
$w('#input1').dispatchEvent(myEvent);
}
Error: TypeError: $w(...).dispatchEvent is not a function
Related
When passing some "query options" while using useQueries() to fetch multiples queries at the same time, these "query options" are not been applied on any query execution (eg: refetchOnWindowFocus is true and I want it to be false).
Example
const slidesID = ['11111', '22222', '33333'];
const COMMON_QUERY_OPTIONS = {
retry: false,
refetchOnWindowFocus: false,
refetchOnMount: false,
} as const;
const slideQueries = useQueries(
slidesID.map((slideID) => {
return {
queryKey: ['slides', 'slide', slideID],
queryFn: () => getSlide(slideID),
COMMON_QUERY_OPTIONS,
};
}),
);
The problem is you are passing in the WRONG way the "query options".
There are two similar but different ways of executing useQuery:
a) common way ( just the 3er param is an {object} )
const result = useQuery(queryKey,queryFn, {
retry: false,
refetchOnWindowFocus: false,
refetchOnMount: false,
} )
b) the object syntax way (all the params are at the same level inside a global object)
const result = useQuery({queryKey, queryFn, retry: false,
refetchOnWindowFocus: false,
refetchOnMount: false,
})
In your example, you are using the 'the object syntax way' but passing the "query options" as the 'common way'. To fix it just apply a ...spread to correctly pass the options.
FIXED Example
const slidesID = ['11111', '22222', '33333'];
const COMMON_QUERY_OPTIONS = {
retry: false,
refetchOnWindowFocus: false,
refetchOnMount: false,
} as const;
const slideQueries = useQueries(
slidesID.map((slideID) => {
return {
queryKey: ['slides', 'slide', slideID],
queryFn: () => getSlide(slideID),
...COMMON_QUERY_OPTIONS, //notice the ... here
};
}),
);
I'm trying to set the liveChatAvailable value to true and isLoading value to false once the cripClient element loads to the page.
When the observer object is within a function the if (crispClient) code never runs.
After some research, it seems that it might have something to do with the code needing to be asynchronous but I don't really know how to go about it so a push in the right direction would be great.
Update:
I made the mixin run the code on mounted() instead of doing it inside of the component to see if that would make a difference but it didn't.
LiveChatAvailability.js
export const LiveChatAvailability = {
data() {
return {
isLoading: true,
liveChatAvailable: false
}
},
methods: {
setLiveChatAvailability() {
const crispClient = document.querySelector('.crisp-client');
const observer = new MutationObserver((mutations, obs) => {
if (crispClient) {
this.loading = false;
this.liveChatAvailable = true;
obs.disconnect();
return;
}
observer.observe(document, {
childList: true,
subtree: true
});
});
}
}
}
LiveChatButton.vue
<template>
<button v-if="liveChatAvailable" #click.prevent="liveChatTrigger">Start a live chat now</button>
</template>
<script>
import {LiveChatAvailability} from '../../../../../public_html/assets/src/js/Vue/Mixins/LiveChatAvailability';
export default {
mixins: [
LiveChatAvailability
],
created() {
this.setLiveChatAvailability();
},
methods: {
liveChatTrigger() {
if (window.$crisp) {
window.$crisp.push(['do', 'chat:open']);
}
}
},
}
</script>
Placing the crispClient const within the MutationObserver code allowed it to work.
export const LiveChatAvailability = {
data() {
return {
isLoading: true,
liveChatAvailable: false
}
},
methods: {
setLiveChatAvailability() {
const observer = new MutationObserver((mutations, obs) => {
if (crispClient) {
const crispClient = document.querySelector('.crisp-client');
this.loading = false;
this.liveChatAvailable = true;
obs.disconnect();
return;
}
});
observer.observe(document, {
childList: true,
subtree: true
});
}
}
}
I have a component where I am defining two objects with default properties, one of which is a callback method.
I am then trying to clone/assign that default object to another variable that my getter is using. Doing this, however, the callback method is never run when the button it is attached to is clicked.
Both object.assign and spread were things I attempted as well, but I may be approaching this incorrectly.
Example code:
// defaults
DEFAULT_SAVE_HANDLER = {
cb: this._modalSaveHandler,
label: "Create Case",
variant: "brand",
action: "createcase",
class: "",
disabled: true,
visible: true
};
DEFAULT_CANCEL_HANDLER = {
cb: this._modalCancelHandler,
label: "Cancel",
variant: "netrual",
class: "btn-left",
action: "close",
disabled: false,
visible: true
};
// Set vars for getter
_save = this.DEFAULT_SAVE_HANDLER;
_cancel = this.DEFAULT_CANCEL_HANDLER;
/* Spread Attempt
_save = { ... this.DEFAULT_SAVE_HANDLER };
_cancel = { ... this.DEFAULT_CANCEL_HANDLER};
*/
/* Assign Attempt
_save = Object.assign({}, this.DEFAULT_SAVE_HANDLER);
_cancel = Object.assign({}, this.DEFAULT_CANCEL_HANDLER);
*/
// Getters
get saveHandler() {
return this._save
}
set saveHandler(props){
this._save = Object.assign({}, this.DEFAULT_SAVE_HANDLER, props)
}
get cancelHandler() {
return this._cancel
}
set cancelHandler(props) {
this._cancel = Object.assign({}, this.DEFAULT_CANCEL_HANDLER, props)
}
// Callbacks
_modalSaveHandler = () => {
console.log("save handler ran");
};
_modalCancelHandler = () => {
console.log("cancel handler ran");
};
// Some random method to update a property on the button
onButtonClick(){
this.saveHandler = { disabled: false };
}
Now when my other component tries to run the callback method I am attempting to pass, it is not hitting it at all.
Is this an issue with a scope or my misunderstanding of how the properties are being cloned/referenced?
UPDATE:
When changing the default object to contain the callback function directly, it works fine.
It seems like the issue happens when trying to reference the callback method versus inline.
DEFAULT_CANCEL_HANDLER = {
//cb: this._modalCancelHandler,
cb: () => {
console.log('this works')
},
label: "Cancel",
variant: "netrual",
class: "btn-left",
action: "close",
disabled: false,
visible: true
};
You need to use a getter if you want to reference keys of the object you are just declaring.
Without the getter, the handler on the original object is already undefined, hence it's not cloned.
const obj = {
_handler() {
console.log('foo')
},
get handler() {
return this._handler
}
}
const clone = { ...obj }
obj.handler()
clone.handler()
Note, that you should not use arrow functions for this because the this keyword will not work the same when doing so.
I think you have a class where your code resides and when you create DEFAULT_OBJECTS the callback functions are undefined.
Try to move callback declaration higher than DEFAULT_SAVE_HANDLER and DEFAULT_CANCEL_HANDLER
Like:
// Callbacks
_modalSaveHandler = () => {
console.log("save handler ran");
};
_modalCancelHandler = () => {
console.log("cancel handler ran");
};
// defaults
DEFAULT_SAVE_HANDLER = {
cb: this._modalSaveHandler,
label: "Create Case",
variant: "brand",
action: "createcase",
class: "",
disabled: true,
visible: true
};
DEFAULT_CANCEL_HANDLER = {
cb: this._modalCancelHandler,
label: "Cancel",
variant: "netrual",
class: "btn-left",
action: "close",
disabled: false,
visible: true
};
//....
I need to catch click event on button and changing event type only and dispatching it again
something similar below which is in jquery but I want to do it in angular
button.on("click", function(event) {
var newEvent = $.extend({}, event, { type: "dxcontextmenu" });
event.stopPropagation();
$(this).trigger(newEvent);
});
I am able to do dispatchEvent but Event or MouseEvent constructor doesn't have params for screenX or clientX or ...
I tried to use spread operator or Object.Assign but only isTrusted and type properties will be copied.
my code is
onClick(event:any) {
event.stopPropagation();
console.log(event);
const newEvent = Object.assign({}, event, { type: 'dxcontextmenu' });
console.log(newEvent);
event.target.dispatchEvent(newEvent);
// event.target.dispatchEvent(new Event('dxcontextmenu', { bubbles: true }));
}
this is the stackblitz link to it
I found the solution in case other having same problem
openContextMenu(event: MouseEvent)
{
if (event.target)
{
const newEvent = new MouseEvent('dxcontextmenu', { bubbles: true });
newEvent.initMouseEvent(
'dxcontextmenu',
true,
false,
event.view,
event.detail,
event.screenX,
event.screenY,
event.clientX,
event.clientY,
event.ctrlKey,
event.altKey,
event.shiftKey,
event.metaKey,
event.button,
event.relatedTarget
);
event.stopPropagation();
event.target.dispatchEvent(newEvent);
}
}
When I execute my tests locally they pass with no problems but when tests proceed on the server I get:
TypeError: MouseEventConstructor is not a constructor (evaluating 'new MouseEvent('mousedown',
EXEC : error : TypeError: MouseEventConstructor is not a constructor (evaluating 'new MouseEvent('mousedown',
{
'which': 1,
'view': window,
'bubbles': true,
'cancelable': true
})')
for the code:
HTMLElement.prototype.mouseDownLeftButton = function () {
var event = new MouseEvent('mousedown',
{
'which': 1,
'view': window,
'bubbles': true,
'cancelable': true
});
this.dispatchEvent(event);
};
which is totally fine. Is there any other way to create a new MouseEvent ?
There is a polyfill from MDN that will resolve the issue:
https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/MouseEvent#Polyfill
(function (window) {
try {
new MouseEvent('test');
return false; // No need to polyfill
} catch (e) {
// Need to polyfill - fall through
}
// Polyfills DOM4 MouseEvent
var MouseEvent = function (eventType, params) {
params = params || { bubbles: false, cancelable: false };
var mouseEvent = document.createEvent('MouseEvent');
mouseEvent.initMouseEvent(eventType, params.bubbles, params.cancelable, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
return mouseEvent;
};
MouseEvent.prototype = Event.prototype;
window.MouseEvent = MouseEvent;
})(window);
Most likely your local test infra uses real browser and on server it uses PhantomJS.
The latter still doesn't support new MouseEvent: https://github.com/ariya/phantomjs/issues/11289
I had to do the following trick to make tests pass:
function createMouseEvent(typeArg: string): MouseEvent {
let event = document.createEvent('MouseEvent');
event.initMouseEvent(typeArg,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined);
return event;
}