I have a form that places a user's inputs onto the DOM, as well as removing them. The issue is if someone presses the remove button when no inputs are logged onto the DOM it will throw an error to the console. I attempted an IF statement but it doesn't work, The code which I have used is: (h6_w === "" || h6_w == null) { return false; }.
The error which the console is throwing is: app.js:210 Uncaught TypeError: Cannot read property 'remove' of undefined at HTMLAnchorElement. <anonymous(app.js:210)
// Delete From The Dom.
const delBtn = document.querySelector('.del-btn');
delBtn.addEventListener('click', (e) => {
// Remove Form Input.
let h6_w = document.querySelectorAll('.h6_weight_class');
// Empty String.
if (h6_w === "" || h6_w == null) {
return false;
} else {
// Remove Child
h6_w[h6_w.length - 1].remove();
};
});
// Add User's input To The Dom.
const addDom = document.querySelector('.add-dom');
const wForm = document.querySelector('.weight-form');
wForm.addEventListener('submit', (e) => {
e.preventDefault();
// Get Input Value.
const value = wForm.querySelector('input[type="number"]').value;
const value1 = wForm.querySelector('input[type="text"]').value;
// Create Elements.
const h6_weight = document.createElement('h6');
// Adding Id.
h6_weight.classList.add('h6_weight_class');
// Add Content.
h6_weight.textContent = value + value1;
// Append To Dom.
addDom.appendChild(h6_weight);
});
Related
I cannot figure out for the life of me how PackId is undefined according to the error: TypeError: Cannot read property 'PackId' of undefined.
What I'm doing here is: I'm deleting an object that's inside of a collection (which's happening successfully) but I'd also like to eventually display the response correctly which should consist of packIdsOwned and packsOwnedMetadata arrays being populated.
Why's PackId null in the packIdsOwned.push(packsOwned[i].PackId); line and how can I fix it?
const db = client.db("myDb");
let collection = db.collection("Players");
let result = null;
let packIdsOwned = [];
let packsOwnedMetadata = [];
let packIdInput = Profile.PackIdInput; // user input
let packsOwned = result.packsOwned;
// Delete object in the document
collection.updateOne({"userName": result['userName']}, { $pull: { packsOwned: { PackId: packIdInput }}});
// Remove the pack ID from the response that's been deleted in the document
for(let i = 0; i < packsOwned.length; i++) {
if (packsOwned[i].PackId == packIdInput) {
let removePackId = packsOwned.splice(i, 1); // find the PackId in the document and delete it
removePackId = null;
}
// this is for the response but the below line is throwing off the whole program
packIdsOwned.push(packsOwned[i].PackId); // it's saying this PackId value is null
packsOwnedMetadata.push({
PackID : packsOwned[i].PackId
});
}
You remove the index and than you are trying to read that element you just removed.
let removePackId = packsOwned.splice(i, 1); <-- You remove it
packIdsOwned.push(packsOwned[i].PackId); <-- You try to read it.
I am trying to get my form to give an alert and prevent save if it meets a certain criteria (the if statement) and save if anything else but if I stick preventDefault inside the IF it still allows me to save.
I have tried putting it outside the IF but then no matter what I can't save the form and my formContext.data.save() doesn't work.
function denyCreateVariationSor(executionContext)
{
debugger;
var id = Xrm.Page.getAttribute("gilm_variation").getValue()[0].id;
var url = 'gilmartins-test.crm11.dynamics.com/.../gilm_variations eq ' + id + ')';
var variationStatus;
var formContext = executionContext.getFormContext();
fetch(url).then(response => response.json()).then(data =>
{
var arr = data.value;
variationStatus = arr[0]["gilm_variationstatus"];
if (variationStatus != 870110000)
{
executionContext.getEventArgs().preventDefault();
alert("You can't add a SOR onto a completed/cancelled variation");
}
else
{
formContext.data.save()
}
});
}
First of all I'm beginner in javascript. I have this data data.responseJSOn.errors -
Currently I'm displaying the errors like this way -
var errors = data.responseJSON.errors;
console.log(errors);
errors.title &&
errors.title.forEach(function(messageText) {
displayError(messageText);
});
errors.message &&
errors.message.forEach(function(messageText) {
displayError(messageText);
});
How can I display errors from there by using single code instead of predefined errors.title or errors.message.
expected code like -
var errors = data.responseJSON.errors;
var list = ["title", "message"];
list.forEach(function(item) {
errors.item &&
errors.item.forEach(function(messageText) {
displayError(messageText);
});
});
How can I fix it to get output.
You can try something more generic regardless of the key names in object data.responseJSON.errors
var errors = data.responseJSON.errors;
var list = ["title", "message"]; // valid keys for which we need to show message
for (key in errors) {
// check if key is valid and is array
if(list.includes(key) && Array.isArray(errors[key])) {
errors[key].map((msg) => {
displayError(msg);
})
}
}
In the case you're going to need the [] syntax to access a field of the errors object with the value of a variable:
var errors = data.responseJSON.errors;
var list = ["title", "message"];
list.forEach(function(item) {
errors[item] &&
errors[item].forEach(function(messageText) {
displayError(messageText);
});
});
You can access the respective property using []:
var errors = data.responseJSON.errors;
var list = ["title", "message"];
list.forEach(function(item) {
errors[item] &&
errors[item].forEach(function(messageText) {
displayError(messageText);
});
});
Otherwise (and as a better alternative), you can use the for...in loop syntax to access enumerable object properties:
var errors = data.responseJSON.errors;
var list = ["title", "message"];
errors.forEach(function(error) {
for (property in error) {
displayError(error[property]);
}
});
here you don't have to explicitly mention the type of keys the error message has. Even in future, if messages and title changes you don't have to modify the code again.
const messageText = (message: string) => {
console.log('message', message)
}
Object.keys(response).map((error) => response[error].length && response[error].forEach((message: string) => messageText(message)));
I've been working on this for two days now and I still can't figure out why my elements are sometimes either returning null or other times returning undefined but never returning the properties themselves. I've set their ID's in the respective HTML file and I still get null or undefined.
I've tried using setTimeout() but that didn't work because I was redirecting to a new page. I tried using an event listener on the document with DOMContentLoaded. I've even tried window.onload
var userEmailDisplay;
var newPaswordInput;
var confNewPaswordInput;
var submitNewPasswordBtn;
const urlParams = getAllUrlParams(window.location.href);
const actionCode = urlParams.oobCode;
window.onload = () => {
var doc = document;
switch (urlParams.mode) {
case 'resetPassword':
handleResetPassword(actionCode);
break;
case 'recoverEmail':
handleRecoverEmail(actionCode);
break;
case 'verifyEmail':
handleVerifyEmail(actionCode);
break;
}
// get new password elements
/* if (window.location.href.indexOf("new-password") > -1) {
userEmailDisplay = doc.getElementById('account-email-new-pswd');
newPaswordInput = doc.getElementById('new-password-input');
confNewPaswordInput = doc.getElementById('conf-new-password-input');
submitNewPasswordBtn = doc.getElementById('update-pswd-sub-btn');
} */
}
function handleResetPassword(actionCode) {
// Verify the password reset code is valid.
auth.verifyPasswordResetCode(actionCode).then(function (email) {
window.location.href = "https://couch-potato-880f0.firebaseapp.com/email/new-password.html";
console.log("code verified");
confirmThePswdReset(actionCode, email);
}).catch(function (error) {
console.error(error);
});
}
function confirmThePswdReset(actionCode, email) {
window.onload = () => {
userEmailDisplay = document.getElementById('account-email-new-pswd');
newPaswordInput = document.getElementById('new-password-input');
confNewPaswordInput = document.getElementById('conf-new-password-input');
submitNewPasswordBtn = document.getElementById('update-pswd-sub-btn');
console.log(submitNewPasswordBtn + ' + ' + userEmailDisplay);
if (submitNewPasswordBtn && userEmailDisplay) {
submitNewPasswordBtn.addEventListener('click', function (e) {
e.preventDefault();
const accountEmail = email;
console.log('submit btn clicked');
const newPassword = newPaswordInput.value;
const confNewPasswordValue = confNewPaswordInput.value;
userEmailDisplay.innerHTML = `Email: ${accountEmail}`;
if (newPassword != confNewPasswordValue) {
alert('The new passwords must match!');
return;
}
console.log(newPassword);
// Save the new password.
auth.confirmPasswordReset(actionCode, newPassword).then(function (resp) {
// Password reset has been confirmed and new password updated.
alert("All good");
window.location.replace('/email/confirm-password-reset.html');
}).catch(function (error) {
console.error(error);
});
});
}
}
}
I expect when I click the submit button on the new password page, there's the alert box to pop up saying that everything is good and the password has been reset but that never happens. The code only goes up to the if-statement that checks if submitNewPasswordBtn and userEmailDisplay exist and are not null. I know that because I never get an output log saying that the submit button was clicked. Sometimes I never even get the output checking that submitNewPasswordBtn and userEmailDisplay exist and have values.
I have a variable mutedUser which I would like to have persist to another function. I am having a bit of trouble with the variable persisting outside the click event. What would be the best way to have it so the "return mutedUser" would keep the "muted" string addition based on the conditions of the if statement being met? Thanks!
*The console.log's were me checking to see where the persistance stops
this.isUserMuted = function isUserMuted(payload) {
var mutedUser = '';
// If mute button is clicked place them into muted users list
// check for duplicates in list
$("#messages-wrapper").off('click', '.message button.muteButton');
$("#messages-wrapper").on('click', '.message button.muteButton', function(e) {
$('#unMute').show();
//create userId reference variable
var chatUserID = parseInt($(this).parent().parent().attr("data-type"));
//store userId in muted user object
mutedUsers[chatUserID] = {};
mutedUsers[chatUserID].id = chatUserID;
mutedUsers[chatUserID].muted = true;
if (mutedUsers[chatUserID] !== null && mutedUsers[chatUserID].id === payload.a) {
console.log("user is now muted");
mutedUser += ' muted';
console.log(mutedUser + 1);
}
console.log(mutedUser + 2);
});
return mutedUser;
};
If I understood what you're trying to do (by looking at the code), this would be the best approach:
// If mute button is clicked place them into muted users list
// check for duplicates in list
$("#messages-wrapper").off('click', '.message button.muteButton');
$("#messages-wrapper").on('click', '.message button.muteButton', function(e) {
$('#unMute').show();
//create userId reference variable
var chatUserID = parseInt($(this).parent().parent().attr("data-type"));
//store userId in muted user object
mutedUsers[chatUserID] = {};
mutedUsers[chatUserID].id = chatUserID;
mutedUsers[chatUserID].muted = true;
});
this.isUserMuted = function isUserMuted(payload) {
var mutedUser = '';
if (mutedUsers[payload.a] !== null) {
mutedUser += ' muted';
}
return mutedUser;
};
The code retains the array of mutedUsers, and isUserMuted function checks if provided user is in that array. In the code you provided, you would attach a new event handler every time isUserMuted function is called..
The isUserMuted function could even be shortened to:
this.isUserMuted = function isUserMuted(payload) {
return mutedUsers[payload.a] !== null ? ' muted' : '';
};
Edit
Sorry, my mistake. Another way is to pass in that variable, i.e.
this.isUserMuted = function isUserMuted(payload, isMuted) {
isMuted = '';
// If mute button is clicked place them into muted users list
// check for duplicates in list
$("#messages-wrapper").off('click', '.message button.muteButton');
$("#messages-wrapper").on('click', '.message button.muteButton', function(e) {
$('#unMute').show();
//create userId reference variable
var chatUserID = parseInt($(this).parent().parent().attr("data-type"));
//store userId in muted user object
mutedUsers[chatUserID] = {};
mutedUsers[chatUserID].id = chatUserID;
mutedUsers[chatUserID].muted = true;
if (mutedUsers[chatUserID] !== null && mutedUsers[chatUserID].id === payload.a) {
console.log("user is now muted");
isMuted += ' muted';
console.log(mutedUser + 1);
}
console.log(mutedUser + 2);
});
return isMuted;
};
You can't. If you return a string from the function, it will always be passed by value, i.e. copied; and it's value will not change any more. You would need to return a function that can access the current value of the local variable, or an object with a property that is changing.
As you already seem to have an object, option#2 will fit in well here:
function User() { // or whatever you have
…
var user = this;
// If mute button is clicked place them into muted users list
// check for duplicates in list
$("#messages-wrapper").on('click', '.message button.muteButton', function(e) {
$('#unMute').show();
//store userId in muted user object
mutedUsers[user.id] = user;
user.muted = true;
});
this.muted = false;
this.isUserMuted = function() {
return this.muted ? ' muted' : '';
}
}