I am trying to call an onchange function on a form select element, currently working with jQuery, but want to switch to Vanilla JS. I am using the closest method on the child element to get the parent, like so;
var $currencyForm = $('.shopify-currency-form select').parents('form');
And have this JS to replicate the lack of the closest function, but keep getting console errors wherby a null value is returned when reading 'parentNode'. See below;
//currencyForm is our parent selector
const currencySelect = document.querySelector('.shopify-currency-form select');
const currencyForm = document.querySelector('form');
//partams are select(child) and form(parent)
function getParentEl(el, parentSelector) {
if (parentSelector === undefined) {
parentSelector = document;
}
var parents = [];
var p = el.parentNode;
while (p !== parentSelector) {
var o = p;
parents.push(o);
p = o.parentNode;
}
parents.push(parentSelector);
return parents;
}
const formInit = getParentEl(currencySelect, currencyForm);
//The parent node should be the last element
const selectEl = parents[parents.length-1];
console.log(selectEl);
Thanks
You're getting null I think because your parent selector - .shopify-currency-form select - refers to an element that doesn't exist or that isn't accessible at the time you look for it. Rather than check for undefined here...
if (parentSelector === undefined) {
check for null...
if (parentSelector === null) {
and then this block will run, assigning another element as the value of parentSelector if that's what you'd like to happen.
You also need to move the initial declaration of your parents var out of local scope in your function in order to access it for the check you perform at the end.
Here's a fiddle with some changes and a test case for a valid class name passed in for the parent el and a made up one so you can perhaps see what's going on a bit better. Assuming a valid parent el class name is assigned and the parent el is available, this runs without any errors:
https://jsfiddle.net/abgregs/3L7mzory/2/
HTML
<!-- <body> -->
<div class="parent">
<div class="first-child">
<div class="my-target-element">
</div>
</div>
</div>
<!-- <body> -->
JS
const currencySelect = document.querySelector('.my-target-element');
// I think that selector is giving you null, but then you're checking for undefined...
// I gave it a made up class here to replicate...
const currencyForm = document.querySelector('.made-up-selector');
// try uncommenting this and comment out the line above, it will work too but there will be fewer els in our parents array...
/* const currencyForm = document.querySelector('.parent'); */
// moved out of local scope...
var parents = [];
function getParentEl(el, parentSelector) {
// changed from checking undefined to checking null here...
if (parentSelector === null) {
parentSelector = document.documentElement;
}
// move this outside of local scope...
/* var parents = []; */
console.log('parentSelector: ', parentSelector);
var p = el.parentNode;
while (p !== parentSelector) {
var o = p;
parents.push(o);
p = o.parentNode;
}
console.log(parents.length)
parents.push(parentSelector);
return parents;
};
const formInit = getParentEl(currencySelect, currencyForm);
//The parent node should be the last element
const selectEl = parents[parents.length-1];
console.log(selectEl);