trigger a method from inside another function - javascript

I have a method that sends data to the database and can be triggered from a button using #click but I want to trigger it from another function by calling it in conditional function any one can help? the post is edited so I want to add the addPatient method called right after submitted notification is triggered in else{}
onSubmit () {
namefRef.value.validate()
namelRef.value.validate()
birthdateRef.value.validate()
if (namefRef.value.hasError || namelRef.value.hasError || birthdateRef.value.hasError ) {
// form has error
}
else if (gender.value !== 'male'&& gender.value !== 'female') {
$q.notify({
color: 'negative',
message: 'You need to choose a gender'
})
}
else {
$q.notify({
icon: 'done',
color: 'positive',
message: 'Submitted',
}),
loadinga.value = true
setTimeout(() => {loadinga.value = false }, 300)
}
},
}
},
data() {
return{
patient:{
id:uid(),
caption:'',
namef:'',
namel:'',
age:'',
lastappointment:'',
location:'',
photo:null,
date:Date.now()
},
loading:false,
}
},
methods:{
addPatient() {
let formData = new FormData()
formData.append('id', this.patient.id)
formData.append('index', this.patient.index)
formData.append('namef', this.namef)
formData.append('namel', this.namel)
formData.append('age', this.patient.age)
formData.append('date', this.patient.date)
formData.append('lastappointment', this.patient.lastappointment)
//* formData.append('file', this.patient.photo, this.patient.id + '.png')
this.$axios.post(`${ process.env.API}/createPatient`, formData).then(
response => {
console.log('response:',response)
}).catch(err => {
console.log('err:',err)
})
}

Related

Display notification pop-up box on open-source CRM

I am using a vtiger Crm system and I would like to use the pop up notification to display my own messages. I wrote an event handler that triggers after model save, in this handler I would like to call the notification box with my own message.
Here is a working example that is from the 'Products' module handlers, this code was pre-written, it checks if there were duplicate item numbers and shows a message 'LBL_DUPLICATE_item_number' in the pop-up box
class Products_DuplicateItemNumber_Handler
{
/**
* EditViewPreSave handler function.
*
* #param App\EventHandler $eventHandler
*/
public function editViewPreSave(App\EventHandler $eventHandler)
{
$recordModel = $eventHandler->getRecordModel();
$response = ['result' => true];
$fieldModel = $recordModel->getModule()->getFieldByName('item_number');
if ($fieldModel->isViewable() && ($item_number = $recordModel->get('item_number'))) {
$queryGenerator = new \App\QueryGenerator($recordModel->getModuleName());
$queryGenerator->setStateCondition('All');
$queryGenerator->setFields(['id'])->permissions = false;
$queryGenerator->addCondition($fieldModel->getName(), $item_number, 'e');
if ($recordModel->getId()) {
$queryGenerator->addCondition('id', $recordModel->getId(), 'n');
}
if ($queryGenerator->createQuery()->exists()) {
$response = [
'result' => false,
'hoverField' => 'item_number',
'message' => App\Language::translate('LBL_DUPLICATE_item_number', $recordModel->getModuleName())
];
}
}
return $response;
}
}
However, when i try to return $respone in 'editViewPreSave' of another module, nothing happens.
After some digging around i found out that the system uses 'Pnotify' library to show the pop up message, and i belive it's being called in a js file called 'edit.js' in this path 'public_html/layouts/basic/modules/Vtiger/resources'
preSaveValidation: function (form) {
const aDeferred = $.Deferred();
if (form.find('#preSaveValidation').val()) {
document.progressLoader = $.progressIndicator({
message: app.vtranslate('JS_SAVE_LOADER_INFO'),
position: 'html',
blockInfo: {
enabled: true
}
});
let formData = new FormData(form[0]);
formData.append('mode', 'preSaveValidation');
AppConnector.request({
async: false,
url: 'index.php',
type: 'POST',
data: formData,
processData: false,
contentType: false
})
.done((data) => {
document.progressLoader.progressIndicator({ mode: 'hide' });
let response = data.result;
for (let i = 0; i < response.length; i++) {
if (response[i].result !== true) {
app.showNotify({
text: response[i].message ? response[i].message : app.vtranslate('JS_ERROR'),
type: 'error'
});
if (response[i].hoverField != undefined) {
form.find('[name="' + response[i].hoverField + '"]').focus();
}
}
}
aDeferred.resolve(data.result.length <= 0);
})
.fail((textStatus, errorThrown) => {
document.progressLoader.progressIndicator({ mode: 'hide' });
app.showNotify({
text: app.vtranslate('JS_ERROR'),
type: 'error'
});
app.errorLog(textStatus, errorThrown);
aDeferred.resolve(false);
});
} else {
aDeferred.resolve(true);
}
return aDeferred.promise();
},
I believe that 'app.showNotify' is the function called to display the pop-up box, yet i'm not sure how to replicate the code for my own use, i would like to know the best approach to do this

Chrome extension - button listener on notification executes multiple times

I am writing a chrome extension that makes requests to an API and I have noticed that after I create a notification from background script using chrome's notification API, the listeners on the buttons from the notification are executed multiple times. on the first run only once and then increasing. I figured that the listeners just add up on the page but I couldn't find a way to sort of refresh the background page.
This is the function that creates the notification and it's listeners.
var myNotificationID
const displayNotification=(userEmail, password, website,username) =>{
chrome.notifications.create("", {
type: "basic",
iconUrl: "./icon128.png",
title: "PERMISSION",
requireInteraction: true,
message: "question",
buttons: [{
title: "YES",
}, {
title: "NO",
}]
}, function(id) {
myNotificationID = id;
})
chrome.notifications.onButtonClicked.addListener(function(notifId, btnIdx) {
if (notifId === myNotificationID) {
if (btnIdx === 0) {
console.log('inserting')
try{
fetch (`http://localhost:8080/users/${userEmail}/accounts`,{
})
}catch(err){
}
} else if (btnIdx === 1) {
console.log('clearing')
chrome.notifications.clear(myNotificationID)
}
}
});
}
And this is where the function is called
chrome.runtime.onMessage.addListener((message, sender, response)=>{
if(message.message === 'showNotification'){
console.log('received insert')
displayNotification(message.userEmail,message.password, message.currentSite,message.username)
response({status:"received"})
}
})
the fetch within the listener is executed multiple times but the log from the onMessage listener is only displayed once, so the listener is the problem here.
I tried chrome.notifications.onButtonClicked.removeListener(), but as i mentioned there was no success.
Are there any other ways in which i could clean the listeners from the background script once they are used?
Using a notification store:
const notificationsByID = {};
chrome.notifications.onButtonClicked.addListener((notifId, btnIdx) => {
// Avoid access to the notification if not registered by displayNotification
if (!notificationsByID[ notifId ]) { return null; }
if (btnIdx === 0) {
console.log('inserting')
try{
fetch (`http://localhost:8080/users/${ notificationsByID[ notifId ].userEmail }/accounts`,{ /**/ });
}catch(err){
console.log(err);
}
delete notificationsByID[ notifId ]; // Cleanup
} else if (btnIdx === 1) {
console.log('clearing')
chrome.notifications.clear(myNotificationID);
delete notificationsByID[ notifId ]; // Cleanup
}
});
chrome.notifications.onClosed.addListener((notifId) => {
if (notificationsByID[ notifId ]) { delete notificationsByID[ notifId ]; }
});
const displayNotification=(userEmail, password, website,username) =>{
chrome.notifications.create("", {
type: "basic",
iconUrl: "./icon128.png",
title: "PERMISSION",
requireInteraction: true,
message: "question",
buttons: [{ title: "YES", }, { title: "NO", }]
}, function(id) {
// Insertion
notificationsByID[ id ] = { userEmail, password, website,username };
})
}

Javascript - prevent navigation during file upload

I have a vue component for video upload, where I am warning a user when he tries to navigate away during the video upload that he will lose the file if he does so, like this:
ready() {
window.onbeforeunload = () => {
if (this.uploading && !this.uploadingComplete && !this.failed) {
this.confirm('Are you sure you want to navigate away? Your video won't be uploaded if you do so!');
}
}
}
I am using sweetalert to alert the user about it. But how can I then make it stay on the same page, and prevent the navigation away before he confirms that he wants to navigate away?
This is the whole component:
<script>
function initialState (){
return {
uid: null,
uploading: false,
uploadingComplete: false,
failed: false,
title: null,
link: null,
description: null,
visibility: 'private',
saveStatus: null,
fileProgress: 0
}
}
export default {
data: function (){
return initialState();
},
methods: {
fileInputChange() {
this.uploading = true;
this.failed = false;
this.file = document.getElementById('video').files[0];
this.store().then(() => {
var form = new FormData();
form.append('video', this.file);
form.append('uid', this.uid);
this.$http.post('/upload', form, {
progress: (e) => {
if (e.lengthComputable) {
this.updateProgress(e)
}
}
}).then(() => {
this.uploadingComplete = true
}, () => {
this.failed = true
});
}, () => {
this.failed = true
})
},
store() {
return this.$http.post('/videos', {
title: this.title,
description: this.description,
visibility: this.visibility,
extension: this.file.name.split('.').pop()
}).then((response) => {
this.uid = response.json().data.uid;
});
},
update() {
this.saveStatus = 'Saving changes.';
return this.$http.put('/videos/' + this.uid, {
link: this.link,
title: this.title,
description: this.description,
visibility: this.visibility
}).then((response) => {
this.saveStatus = 'Changes saved.';
setTimeout(() => {
this.saveStatus = null
}, 3000)
}, () => {
this.saveStatus = 'Failed to save changes.';
});
},
updateProgress(e) {
e.percent = (e.loaded / e.total) * 100;
this.fileProgress = e.percent;
},
confirm(message) {
swal({
title: message,
text: null,
type: "warning",
showCancelButton: true,
cancelButtonText: "Cancel",
cancelButtonColor: '#FFF',
confirmButtonColor: "#2E112D",
confirmButtonText: "Yes, delete"
}).then(function(){
this.$data = initialState();
}.bind(this), function(dismiss) {
// dismiss can be 'overlay', 'cancel', 'close', 'esc', 'timer'
if (dismiss === 'cancel') { // you might also handle 'close' or 'timer' if you used those
// ignore
} else {
throw dismiss;
}
})
}
},
ready() {
window.onbeforeunload = () => {
if (this.uploading && !this.uploadingComplete && !this.failed) {
this.confirm('Are you sure you want to navigate away? Your video won't be uploaded if you do so!');
}
}
}
}
</script>
Mozilla documentation suggests
window.onbeforeunload = function(e) {
var dialogText = 'Dialog text here';
e.returnValue = dialogText;
return dialogText;
};
and also states that:
Since 25 May 2011, the HTML5 specification states that calls to window.alert(), window.confirm(), and window.prompt() methods may be ignored during this event. See the HTML5 specification for more details.
Source contains many other details regarding reasons and what to expect from modern browsers.
This question seems to be a duplicate of yours.
This answer suggests that to avoid weird browser behaviour you should set handler only when it's to prevent something (that is while navigating away should trigger a confirmation dialog)
But how can I then make it stay on the same page, and prevent the navigation away before he confirms that he wants to navigate away?
Add return false; to stop the event.
if (this.uploading && !this.uploadingComplete && !this.failed) {
this.confirm("Are you sure you want to navigate away? Your video won't be uploaded if you do so!");
return false; // <==== add this
}
return false; does 3 separate things when you call it :
event.preventDefault(); – It stops the browsers default behaviour.
event.stopPropagation(); – It prevents the event from propagating (or “bubbling up”) the DOM.
Stops callback execution and returns immediately when called.

Vue JS Custom directive data binding

I'm creating a custom directive to make a form submit via ajax - however I can't seem to get validation errors to bind to the Vue instance.
I am adding my directive here:
<form action="{{ route('user.settings.update.security', [$user->uuid]) }}" method="POST"
enctype="multipart/form-data" v-ajax errors="formErrors.security" data="formData.security">
My directive looks like:
Vue.directive('ajax', {
twoWay: true,
params: ['errors', 'data'],
bind: function () {
this.el.addEventListener('submit', this.onSubmit.bind(this));
},
update: function (value) {
},
onSubmit: function (e) {
e.preventDefault();
this.vm
.$http[this.getRequestType()](this.el.action, vm[this.params.data])
.then(this.onComplete.bind(this))
.catch(this.onError.bind(this));
},
onComplete: function () {
swal({
title: 'Success!',
text: this.params.success,
type: 'success',
confirmButtonText: 'Back'
});
},
onError: function (response) {
swal({
title: 'Error!',
text: response.data.message,
type: 'error',
confirmButtonText: 'Back'
});
this.set(this.vm, this.params.errors, response.data);
},
getRequestType: function () {
var method = this.el.querySelector('input[name="_method"]');
return (method ? method.value : this.el.method).toLowerCase();
},
});
And my VUE instance looks like:
var vm = new Vue({
el: '#settings',
data: function () {
return {
active: 'profile',
updatedSettings: getSharedData('updated'),
formData: {
security: {
current_password: ''
}
},
formErrors: {
security: []
},
}
},
methods: {
setActive: function (name) {
this.active = name;
},
isActive: function (name) {
if (this.active == name) {
return true;
} else {
return false;
}
},
hasError: function (item, array, sub) {
if (this[array][sub][item]) {
return true;
} else {
return false;
}
},
isInArray: function (value, array) {
return array.indexOf(value) > -1;
},
showNotification: function () {
if (this.updatedSettings) {
$.iGrowl({
title: 'Updated',
message: 'Your settings have been updated successfully.',
type: 'success',
});
}
},
}
});
However, when I output the data, the value for formErrors.security is empty
Any idea why?
The issue is with the this.set(/* ... */) line. this.set doesn't work the same as Vue.set or vm.$set.
this.set attempts to set the path that you passed to the directive: v-my-directive="a.b.c". So running this.set('foo') will attempt to set $vm.a.b.c to 'foo'.
What you want to do is this:
(ES6)
this.params.errors.splice(0, this.params.errors.length, ...response.data)
(Vanilla JS)
this.params.errors.splice.apply(this.params.errors, [0,this.params.errors.length].concat(response.data))
That will update whatever Object is tied to the errors param on the DOM Node. Make sure that you do v-bind:errors="formErrors.security" or :errors="formErrors.security".

Load method of Ext.data.store - how to delay a return statement AND a function call until the data is loaded?

connectLoadRenderStoreAndGetCheckBox: function () {
this.someStore = new Ext.data.Store({
proxy:
reader:
]),
sortInfo: { field: , direction: }
});
this.someStore.load(
{
params:
{
}
});
//I left out parameters; lets assume they are valid and work.
this.someStore.on("load", this._renderColumns, this);
return ([this._getCheckBox()]);
}
On 'load' I want to both execute the function this._renderColumns (which uses the data from the server) and also return a checkbox (which also uses data from the server).
What is a quick & easy way to only return the checkbox after the data is loaded?
_getCheckBox: function () {
if (UseDefault == "y") {
return new Ext.form.Checkbox(
{
fieldLabel:,
itemCls:,
checked: true,
labelStyle:
});
}
else {
return new Ext.form.Checkbox(
{
fieldLabel:,
itemCls:,
checked: false,
labelStyle:
});
}
},
_renderColumns: function () {
var record2 = this.something.something2(2);
UseDefault = record2.get("UseDefault");
}

Categories

Resources