Access objects by a combination of an object and two paths

I would like to combine an object, a path in a variable and a path, something like explained in https://stackoverflow.com/a/43849204/14480225 but with 3 "parts".

Here is minimal reproducible example:
I want the combine() function to print selector[0].children[foo].textContent or selector[0].children[foo].children[0].textContent depending on bar value.

const selector = document.getElementsByClassName('main')
const foo = 0
let bar = ''

const toggle = () => {
  if (bar === '') bar = '.children[0]'
  else bar = ''
}

const test = () => {
  console.log(combine('selector[0].children[foo]', bar, '.textContent'))
  //I want a function like combine() that will print 'selector[0].children[foo].textContent' or 'selector[0].children[foo].children[0].textContent' depending on bar value.
}
<div class='main'>
  <h1>Hello<span>world</span></h1>
  <button onclick='toggle()'>toggle</button>
  <button onclick='test()'>test</button>
</div>

I have a class that is returning multiple similar properties (10). My constructor inputs a value that can be used to determine something like bar in the minimal example. Each property by just changing something like bar in the minimal example can have the intended output.
I want something like this to be able to switch between different cases without having to write a massive switch for each bar cases so a lot of code duplication.

23 thoughts on “Access objects by a combination of an object and two paths”

  1. Something like this? But please read about eval() here before using it:
    call javascript object method with a variable

    also:
    call javascript object method with a variable

    const selector = document.getElementsByClassName('main')
    const foo = 0
    let bar = ''
    
    const toggle = () => {
      if (bar === '') bar = '.children[0]'
      else bar = ''
    }
    
    function combine(){
    let result = "selector[0].children[foo]"+bar+".textContent"
    return result
    }
    
    const test = () => {
      console.log(eval(combine()))
      //I want a function like combine() that will print 'selector[0].children[foo].textContent' or 'selector[0].children[foo].children[0].textContent' depending on bar value.
    }
    <div class='main'>
      <h1>Hello<span>world</span></h1>
      <button onclick='toggle()'>toggle</button>
      <button onclick='test()'>test</button>
    </div>
    Reply
  2. What you need to use is querySelector to find the element you are after.

    Read about querySelector and querySelectorAll so you could understand better.

    Using eval is not recommended and it is risky.

    See if you like my idea below.

    const selector = document.getElementsByClassName('main')
    const path = ":nth-child(1)"
    
    function getText(s, p) {
      if (s.length) // Is array
         return Array.from(s).map(x=> x.querySelector(p)?.textContent ?? "").join(" ");
      return  s.querySelector(p)?.textContent;
    }
    
    console.log(getText(selector, path))
    <div class='main'>
      <h1>Hello<span>world</span></h1>
      <button onclick='toggle()'>toggle</button>
      <button onclick='test()'>test</button>
    </div>
    Reply

Leave a Comment